zoukankan      html  css  js  c++  java
  • 【NOI2019】机器人

    题面

    https://www.luogu.org/problem/P5469

    题解

    这里,我们只考虑$50pts$的区间$dp$做法。

    因为最大值把区间劈成互不影响的两端,我们可以用类似分治的思想设计$dp$,解决这个问题。

    设$f[l][r][x]$为$[l..r]$的最大值为$x$的方案数,转移的时候直接枚举最大值的位置,让左边的最大值小于等于它,让右边的最大值小于它,即可转移。

    注意这类转移和合并石子不同,并不是两个区间的并,而是左区间并最大值并右区间,这样才能充分利用性质。

    因为对于一个区间,可以取得最大值的位置是很少的,所以用记忆化的搜索优化(这更印证了分治思想)更加优美,可以做到更优秀的复杂度。但是我懒得写了。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ri register int
    #define N 55
    #define H 105
    #define LL long long
    #define mod 1000000007
    
    using namespace std;
    
    inline int read() {
      int ret=0,f=0; char ch=getchar();
      while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
      while (ch>='0' && ch<='9') ret*=10,ret+=ch-'0',ch=getchar();
      return f?-ret:ret;
    }
    
    int n,ans=0;
    int c[N],a[N],b[N];
    int f[N][N][H];
    
    int mul(int x,int y) {
        LL z=x; z*=y;
        return (int)(z%mod);
    }
    int jia(int x,int y) {
        x+=y;
        if (x>=mod) x-=mod;
        return x;
    }
    
    int main() {
      n=read();
      int mb=0;
      for (ri i=1;i<=n;i++) a[i]=read(),b[i]=read(),mb=max(mb,b[i]);
    
      for (ri i=0;i<=n;i++) f[i+1][i][0]=1;
      for (ri i=1;i<=n;i++) {
          for (ri j=a[i];j<=b[i];j++) f[i][i][j]=1;
      }
        for (ri l=1;l<=n-1;l++)
            for (ri lb=1,rb;lb+l<=n;lb++) {
                rb=lb+l;
                int pl,pr;
                if ((lb+rb)%2==1) {
                    pl=(lb+rb)/2;
                    pr=(lb+rb)/2+1;
                }
                else {
                    pl=(lb+rb)/2-1;
                    pr=(lb+rb)/2+1;
                }
                for (ri x=pl;x<=pr;x++) {
                    for (ri h=a[x];h<=b[x];h++) {
                        int s1=0;
                        for (ri j=0;j<=h;j++) s1=jia(s1,f[lb][x-1][j]);
                        int s2=0;
                        for (ri j=0;j<h;j++) s2=jia(s2,f[x+1][rb][j]);
                        f[lb][rb][h]=jia(f[lb][rb][h],mul(s1,s2));
                    }
                }
            }
        int ans=0;
        for (ri i=0;i<=mb;i++) ans=jia(ans,f[1][n][i]);
        cout<<ans<<endl;
    }
  • 相关阅读:
    谈谈对《镇魔曲》经济的一些看法
    谈谈对《神武2》经济的一些看法
    关于数值策划在使用Excel表时的一点想法
    游戏系统数值建模过程设计
    制作Excel工作薄目录
    制作当前表所在文件夹中所有文件的动态链接
    Excel各种tips汇总
    关于randbetween连乘的问题
    VBA实现两种方法生成任意概率分布的随机数
    Excel数值、文本相互转换
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11792603.html
Copyright © 2011-2022 走看看