多校第一场:hdu(4301)dp

    题意:把2*n的方格,分成m个部分有多少中分法。

    在孟神的帮助下看懂了第一道dp,,,,

转自解题报告:

      状态表示 f[i][0][j]:前i行已经出现了j部分且第i行的两个格子属于同一部分的方法数

         f[i][1][j]:前i行已经出现了j部分且第i行的两个格子属于不同部分的方法数

        初始条件 f[1][0][1]=f[1][1][2]=1

状态转移

         f[i+1][0][j]=(f[i+1][0][j]+f[i][0][j]+f[i][1][j]*2)%mod;

         f[i+1][0][j+1]=(f[i+1][0][j+1]+f[i][0][j]+f[i][1][j])%mod;

         f[i+1][1][j]=(f[i+1][1][j]+f[i][1][j])%mod;

         f[i+1][1][j+1]=(f[i+1][1][j+1]+f[i][0][j]*2+f[i][1][j]*2)%mod;

         f[i+1][1][j+2]=(f[i+1][1][j+2]+f[i][0][j]+f[i][1][j])%mod;

共12种不同的状态转移(见下图)

 

表示dp 很难,


#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<cstdio>
#include<string>
using namespace std;
const int  MA=1009;
const int mod=100000007;
int n,m;
int  f[MA][2][MA*2];
int main()
{
    memset(f,0,sizeof(f));
    f[1][0][1]=1;
    f[1][1][2]=1;
    for(int i=1;i<=1002;i++)
    {
        for(int j=1;j<=2*i;j++)
        {
         f[i+1][0][j]=(f[i+1][0][j]+f[i][0][j]+f[i][1][j]*2)%mod;
         f[i+1][0][j+1]=(f[i+1][0][j+1]+f[i][0][j]+f[i][1][j])%mod;
         f[i+1][1][j]=(f[i+1][1][j]+f[i][1][j])%mod;
         f[i+1][1][j+1]=(f[i+1][1][j+1]+f[i][0][j]*2+f[i][1][j]*2)%mod;
         f[i+1][1][j+2]=(f[i+1][1][j+2]+f[i][0][j]+f[i][1][j])%mod;
        }
    }

   int cas;
   cin>>cas;
  while(cas--)
  {
    scanf("%d%d",&n,&m);
    int ans=(f[n][1][m]+f[n][0][m])%mod;
    cout<<ans<<endl;
  }
  return 0;
}


你可能感兴趣的:(多校第一场:hdu(4301)dp)