Caesar's Legions(CodeForces-118D) 【DP】
作者:互联网
题目链接:https://vjudge.net/problem/CodeForces-118D
题意:有n1名步兵和n2名骑兵,现在要将他们排成一列,并且最多连续k1名步兵站在一起,最多连续k2名骑兵站在一起,求方案数。
思路:dp[i][j][res1][res2],表示排好了i人,并且当前最后一个人是j(j=1表示步兵, j=2表示骑兵),res1、res2分别表示步兵、骑兵的剩余数量。
xxmlala:真的贼激动啊,有史以来第一次在比赛中做出来非状态压缩的dp!
代码如下:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int mo=1e8; 6 long long dp[220][3][110][110]; 7 int main(){ 8 int n1,n2,k[3]; 9 scanf("%d%d%d%d",&n1,&n2,&k[1],&k[2]); 10 memset(dp,-1,sizeof(dp)); 11 int kk1=min(k[1],n1),kk2=min(k[2],n2); 12 for(int i=1;i<=kk1;i++) 13 dp[i][1][n1-i][n2]=1; 14 for(int i=1;i<=kk2;i++) 15 dp[i][2][n1][n2-i]=1; 16 for(int j=1;j<=n1+n2;j++){ 17 for(int i=1;i<=2;i++){ 18 int re[3]; 19 for(re[1]=0;re[1]<=n1;re[1]++) 20 for(re[2]=0;re[2]<=n2;re[2]++){ 21 if(dp[j][i][re[1]][re[2]]==-1) 22 continue; 23 int kFlag=min(k[3-i],re[3-i]); 24 int kt[3]={0};kt[3-i]=1; 25 for(int jj=1;jj<=kFlag&&jj+j<=n1+n2;jj++){ 26 if(dp[jj+j][3-i][re[1]-kt[1]*jj][re[2]-kt[2]*jj]==-1) 27 dp[jj+j][3-i][re[1]-kt[1]*jj][re[2]-kt[2]*jj]=0; 28 dp[j+jj][3-i][re[1]-kt[1]*jj][re[2]-kt[2]*jj]+=dp[j][i][re[1]][re[2]]%mo; 29 dp[j+jj][3-i][re[1]-kt[1]*jj][re[2]-kt[2]*jj]%=mo; 30 } 31 } 32 } 33 } 34 long long ans=0; 35 if(dp[n1+n2][1][0][0]!=-1) 36 ans+=dp[n1+n2][1][0][0]; 37 if(dp[n1+n2][2][0][0]!=-1) 38 ans+=dp[n1+n2][2][0][0]; 39 ans%=mo; 40 printf("%I64d",ans); 41 return 0; 42 }
标签:int,d%,Caesar,DP,n1,118D,include,n2,dp 来源: https://www.cnblogs.com/xxmlala-fff/p/11668899.html