• 51Nod 1327 棋盘游戏 —— 延迟DP


    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1327

    看博客:https://www.cnblogs.com/Narh/p/9791875.html

    思路就是按列DP,如果不是必须填就先空下这一列,记录一下目前有多少可用的空列,遇到一个 l 的结束时就从中选一些列放上棋子,并乘个排列;

    对于 r,方案数在当前列体现,所以要记录当前列可填的位置;

    注意别漏了状态,当前可转移的状态是填 l,填 r,不填,填在不是 l 也不是 r 的地方四种转移;

    还有各种细节...全仰仗 Narh 提点;

    呆滞了半小时...一对拍就发现...在算 A 的地方别忘了写 (ll) !!!

    好题啊!

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int const xn=55,xm=205,mod=1e9+7;
    int n,m,l[xn],r[xn],f[xm][xm][xm],jc[xm],jcn[xm],sl[xm],sr[xm];
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    ll pw(ll a,int b)
    {
      ll ret=1;
      for(;b;b>>=1,a=(a*a)%mod)
        if(b&1)ret=(ret*a)%mod;
      return ret;
    }
    void init()
    {
      jc[0]=1;
      for(int i=1;i<=m;i++)jc[i]=((ll)jc[i-1]*i)%mod;
      jcn[m]=pw(jc[m],mod-2);
      for(int i=m-1;i>=0;i--)jcn[i]=((ll)jcn[i+1]*(i+1))%mod;
    }
    int A(int n,int m){return (ll)jc[n]*jcn[n-m]%mod;}//(ll)!!!
    void upt(int &x,int y){x+=y; while(x>=mod)x-=mod; while(x<0)x+=mod;}
    int main()
    {
      n=rd(); m=rd(); init();
      for(int i=1;i<=n;i++)l[i]=rd(),r[i]=rd(),sl[l[i]]++,sr[m-r[i]+1]++;
      for(int i=1;i<=m;i++)sr[i]+=sr[i-1];
      f[0][0][0]=1;
      for(int i=0,num=0;i<m;i++,num=num+sl[i])//
        for(int j=max(0,sl[i+1]-1);j<=i-num;j++)//剩余
          for(int k=0;k<=min(i,n);k++)//填r
        {
          if(!f[i][j][k])continue;
          if(sl[i+1])
            upt(f[i+1][j+1-sl[i+1]][k],(ll)f[i][j][k]*A(j+1,sl[i+1])%mod);
          //,printf("f[%d][%d][%d]=%d A(%d,%d)=%lld f[%d][%d][%d]=%d
    ",i,j,k,f[i][j][k],j+1,sl[i+1],A(j+1,sl[i+1]),i+1,j+1-sl[i+1],k,f[i+1][j+1-sl[i+1]][k]);//l
          else upt(f[i+1][j+1][k],f[i][j][k]);//0
          if(sr[i+1]>k&&j>=sl[i+1])
            upt(f[i+1][j-sl[i+1]][k+1],(ll)f[i][j][k]*A(j,sl[i+1])%mod*(sr[i+1]-k)%mod);
          //,printf("sr=%d k=%d f[%d][%d][%d]=%d f[%d][%d][%d]=%d
    ",sr[i+1],k,i,j,k,f[i][j][k],i+1,j-sl[i+1],k+1,f[i+1][j-sl[i+1]][k+1]);//r(+l)
          if(num-sr[i+1]&&j>=sl[i+1])
            upt(f[i+1][j-sl[i+1]][k],(ll)f[i][j][k]*A(j,sl[i+1])%mod*(num-sr[i+1])%mod);
          //,printf("!l!r:f[%d][%d][%d]=%d A=%lld k=%d f[%d][%d][%d]=%d
    ",i,j,k,f[i][j][k],A(j,sl[i+1]),num-sr[i+1],i+1,j-sl[i+1],k,f[i+1][j-sl[i+1]][k]);//!l,!r (+l)
          //            printf("f[%d][%d][%d]=%d
    ",i,j,k,f[i][j][k]);
        }
      int ans=0;
      for(int j=0;j<=m-2*n;j++)upt(ans,f[m][j][n]);
      //,printf("f[%d][%d][%d]=%d
    ",m,j,n,f[m][j][n]);
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    爬虫
    Django
    python多线程
    python基础
    深度学习_1_Tensorflow_1
    人工智能_5_决策树_随机森林
    人工智能_4_k近邻_贝叶斯_模型评估
    人工智能_3_机器学习_概述
    Python re 模块
    Python函数式编程
  • 原文地址:https://www.cnblogs.com/Zinn/p/9799015.html
Copyright © 2020-2023  润新知