【训练题71:动态规划】Building Blocks | Gym102822B
创始人
2024-03-30 07:23:54

【训练题71:动态规划】Building Blocks | Gym102822B

  • 题意
  • 思路
  • 代码

题意

  • Building Blocks | Gym102822B
  • 这是一堆方块物体的三视图

在这里插入图片描述

  • 现在定义正左视图,看到的就是这样的
    在这里插入图片描述
  • 给定 n,mn,mn,m 表示俯视图的矩阵的行和列
    给定 kkk 个条件,第 iii 个条件表示俯视图的第 xix_ixi​ 行第 yiy_iyi​ 列的位置的高为 hih_ihi​
    给定正左视图的每个位置的高度 aia_iai​。注意到一共有 n+mn+mn+m 个位置
    问你所有合法情况的方案数取模 1e9+71e9+71e9+7
    当然满足若某个位置有方块,它的底下一定有方块。
    还要满足对于俯视图的每个位置,必须至少有一个方块。
  • 1≤n,m,k≤1051\le n,m,k\le 10^51≤n,m,k≤105
    1≤ai,hi≤1091\le a_i,h_i\le 10^91≤ai​,hi​≤109
    保证每个条件的位置均不同。

思路

  • 注意到,正左视图的第 iii 个位置影响俯视图两个斜列的位置。
    我们肯定按俯视图一个斜列一个斜列去计算,这样复杂度可以达到 O(n+m)O(n+m)O(n+m)
    首先是处理俯视图位置 (i,j)(i,j)(i,j) 是正左视图第几个斜列,容易得到为 i+j−1i+j-1i+j−1,记作 f(i,j)=i+j−1f(i,j)=i+j-1f(i,j)=i+j−1
    还要处理一下每个斜列还剩下有多少个位置没有填,记作 cnt[i]cnt[i]cnt[i]
  • 注意到,我们考虑当前斜列
    在这里插入图片描述
  • 这一斜列用对角线一划,可以看到对应了正左视图的两个高度,记作 a,ba,ba,b
    自然需要满足的,就是这个斜列位置的最高高度应该为 min⁡(a,b)\min(a,b)min(a,b)
    当然还有,就是对于 aaa 所对应的两个斜列的最大值为 aaa,对 bbb 同理。

    可以感觉到,aaa 还被上一斜列所影响。
    那么很自然就可以想到一个动态规划
    定义 dp[x][0]dp[x][0]dp[x][0] 表示考虑完前 xxx 个斜列,最后一个斜列的最大值还没有取到,或者说还没有满足
    dp[x][1]dp[x][1]dp[x][1] 表示考虑完前 xxx 个斜列,最后一个斜列的最大值取到了,或者说满足了
  • 首先考虑一些非法的情况
    因为有 kkk 个已知条件,这个位置的高度就不能大于它对应正左视图的两个位置的值
    即 h>a[f(x,y)]h>a[f(x,y)]h>a[f(x,y)] 或 h>a[f(x,y)+1]h>a[f(x,y)+1]h>a[f(x,y)+1] 自然非法
    然后对于初始化,即第一斜列我们单独考虑
    第一斜列就是位置 (1,1)(1,1)(1,1)
    如果 a[1]>a[2]a[1]>a[2]a[1]>a[2] 一定是不行的,因为 a[1]a[1]a[1] 就是 (1,1)(1,1)(1,1) 处的高度,那么 a[2]a[2]a[2] 就至少是 a[1]a[1]a[1]
    如果 (1,1)(1,1)(1,1) 的位置是已知条件的话,那么 h(1,1)h_{(1,1)}h(1,1)​ 当然必须等于 a[1]a[1]a[1]
  • 接下来考虑递推转移
    • 首先,假设上一个状态为 dp[i−1][1]dp[i-1][1]dp[i−1][1],即 aaa 已经满足了
      • 如果我们希望 bbb 也满足,即转移到 dp[i][1]dp[i][1]dp[i][1],那么需要 b≤ab\le ab≤a,不然就破坏了正左视图上一位置最大值为 aaa 的条件
        • 如果这一斜列有高度 bbb 了,那么剩余 cntcntcnt 个位置,1∼b1\sim b1∼b 随意填,方案数 bcntb^{cnt}bcnt
        • 如果这一斜列没有高度 bbb,那么我们需要满足 cnt>0cnt>0cnt>0,这些位置可以填 1∼b1\sim b1∼b,且满足至少有一个 bbb
          简单容斥,方案数即为 bcnt−(b−1)cntb^{cnt}-(b-1)^{cnt}bcnt−(b−1)cnt
          但是如果 cnt=0cnt=0cnt=0,那么方案数为 000,不影响
      • 如果我们希望转移到 dp[i][0]dp[i][0]dp[i][0],即目前的 bbb 暂时不取到
        • 如果 b≤ab\le ab≤a 并且这一斜列没有高度 bbb,才是可以的,每个位置 1∼(b−1)1\sim (b-1)1∼(b−1) 随便选
          方案数为 (b−1)cnt(b-1)^{cnt}(b−1)cnt
        • 如果 b>ab>ab>a,那么我们这个位置可以选择的数为 1∼a1\sim a1∼a,注意不能破坏最大值为 aaa 的限制
          方案数为 acnta^{cnt}acnt
    • 如果上一个状态为 dp[i−1][0]dp[i-1][0]dp[i−1][0],那么我们 aaa 就一定要满足,不然就非法了。
      • 如果 a>ba>ba>b,我们最大值要放 aaa 但是又不能超过 bbb,自然无解
      • 如果 a
      • 如果当前斜列有元素 aaa,那么我们自然满足了条件 aaa,且我们能放的元素为 1∼a1\sim a1∼a,即 bbb 无法目前满足
        方案数就是 acnta^{cnt}acnt
      • 如果当前斜列没有元素 aaa,那么我们能放的元素为 1∼a1\sim a1∼a且至少有一个 aaa
        同上方案数为 acnt−(a−1)cnta^{cnt}-(a-1)^{cnt}acnt−(a−1)cnt
        自然需要满足 cnt>0cnt>0cnt>0
        但是如果 cnt=0cnt=0cnt=0,那么方案数为 000,不影响
    • 如果 a=ba=ba=b,那么自然满足了 aaa 也同时满足了 bbb,即转移到 dp[i][1]dp[i][1]dp[i][1]
      转移方案和 a
  • 可以看到,我们只要先预处理一下第 iii 斜列是否存在元素 xxx ,记一个 ump 即可
  • 代码

    • 时间复杂度:O(n+m)O(n+m)O(n+m)
    #include 
    #define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
    using namespace std;
    typedef long long ll;
    void show(){std::cerr << endl;}templatevoid show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}const int MAX = 2e5+50;
    const int MOD = 1e9+7;
    const int INF = 0x3f3f3f3f;
    const ll LINF = 0x3f3f3f3f3f3f3f3f;
    const double EPS = 1e-5;ll qpow(ll a,ll n){/* */ll res = 1LL;while(n){if(n&1)res=res*a%MOD;a=a*a%MOD;n>>=1;}return res;}
    ll qpow(ll a,ll n,ll p){a%=p;ll res = 1LL;while(n){if(n&1)res=res*a%p;a=a*a%p;n>>=1;}return res;}
    ll npow(ll a,ll n){/* */ll res = 1LL;while(n){if(n&1)res=res*a;a=a*a;n>>=1;if(res<0||a<0)return 0;}return res;}
    ll inv(ll a){/* */return qpow(a,MOD-2);}
    ll inv(ll a,ll p){return qpow(a,p-2,p);}unordered_mapM[MAX];
    int aa[MAX];
    int cnt[MAX];
    ll dp[MAX][2];int F(int n,int m){return n + m - 1;
    }int main()
    {int T;scanf("%d",&T);for(int kase = 1;kase <= T;++kase){ll ans = 0;int n,m,k;scanf("%d%d%d",&n,&m,&k);int min_nm = min(n,m);for(int i = 1;i <= n + m;++i){M[i].clear();}for(int i = 1;i <= min_nm;++i){cnt[i] = i;}for(int i = min_nm;i <= n + m - 1;++i){cnt[i] = min_nm;}for(int i = 1;i <= min_nm;++i){cnt[n + m - i] = i;}for(int i = 1;i <= n + m;++i){scanf("%d",&aa[i]);}bool cant = false;for(int i = 1;i <= k;++i){int x,y,h;scanf("%d%d%d",&x,&y,&h);int aim = F(x,y);M[aim][h] = 1;cnt[aim]--;if(h > aa[aim] || h > aa[aim+1]){cant = true;}}if(aa[1] > aa[2]){cant = true;}if(cnt[1] == 0 && !M[1][aa[1]]){cant = true;}if(!cant){// initdp[1][1] = dp[1][0] = 0;if(aa[1] == aa[2]) dp[1][1] = 1;else dp[1][0] = 1;for(int i = 2;i <= n + m - 1;++i){dp[i][0] = dp[i][1] = 0;int a = aa[i],b = aa[i+1];int k = min(a,b);bool ys = M[i][k];int ccnt = cnt[i];ll rem = (qpow(k,ccnt) - qpow(k-1,ccnt) + MOD) % MOD;// dp[i-1][1]if(b <= a){if(ys) dp[i][1] = (dp[i][1] + dp[i-1][1] * qpow(b,ccnt) % MOD) % MOD;else dp[i][1] = (dp[i][1] + dp[i-1][1] * rem % MOD) % MOD;}if(b <= a && !ys){dp[i][0] = (dp[i][0] + dp[i-1][1] * qpow(b-1,ccnt) % MOD) % MOD;}else if(a < b){dp[i][0] = (dp[i][0] + dp[i-1][1] * qpow(a,ccnt) % MOD) % MOD;}// dp[i-1][0]if(a > b){//no solution}else if(a < b){if(ys)  dp[i][0] = (dp[i][0] + dp[i-1][0] * qpow(a,ccnt) % MOD) % MOD;else dp[i][0] = (dp[i][0] + dp[i-1][0] * rem % MOD) % MOD;}else if(a == b){if(ys)  dp[i][1] = (dp[i][1] + dp[i-1][0] * qpow(a,ccnt) % MOD) % MOD;else dp[i][1] = (dp[i][1] + dp[i-1][0] * rem % MOD) % MOD;}
    //                show(i,dp[i][0],dp[i][1]);}ans = dp[n+m-1][1];}printf("Case #%d: %lld\n",kase,ans);}return 0;
    }
    /***/

    相关内容

    热门资讯

    埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
    苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
    北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
    长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
    世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
    应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
    脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
    猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
    demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
    埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
    苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
    北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
    世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
    长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
    应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
    脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
    猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
    demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...