标签:src hid ++ 转移 amp c++ scan 状态转移方程 mod
题意:有n1个步兵和n2骑兵要排成一排,连续步兵数不能超过k1个,连续骑兵数不能超过k2个,问有几种排列方案
算是一个简单的dp, 我一开始的思想是设dp[i][j],i是n1+n2,j表示是步兵还是骑兵,但是发现这样不好转移,如果以后发现不好转移,可以加一维
所以就把它变成了dp[i][j][k],i是步兵,j是骑兵,k是骑兵还是步兵,但是这样说好像不利于理解,不如这样说,i表示用了i个步兵,j表示用了j个骑兵,k表示当前用的是步兵还是骑兵,然后答案肯定是(dp[n1][n1][0]+dp[n1][n1][1])%mod
然后接下来我就卡在了怎么转移上面了,其实我一开始的想法已经比较接近了,但是就是卡了那几下,没进去。其实这个是满足最优子结构的,这不用想,肯定没有后效性,但是怎么转移呢?
不妨假设,当前状态是dp[i][j][0],那么就是表示的状态是已经选了j个骑兵,i-1个步兵,然后当前再选一个步兵,那么怎么当前可以再选一个步兵,就是前面的步兵的数量的连续和不能超过k1,那么这样就可以推出状态转移方程了
下面是代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int mod=100000000; 4 int n1,n2,k1,k2; 5 int dp[110][110][2]; 6 int main(){ 7 scanf("%d%d%d%d",&n1,&n2,&k1,&k2); 8 memset(dp,0,sizeof(dp)); 9 for(int i=1;i<=k1;i++) 10 dp[i][0][0]=1; 11 for(int i=1;i<=k2;i++) 12 dp[0][i][1]=1; 13 for(int i=1;i<=n1;i++){ 14 for(int j=1;j<=n2;j++){ 15 for(int k=1;k<=min(i,k1);k++) dp[i][j][0]=(dp[i][j][0]+dp[i-k][j][1])%mod; 16 for(int k=1;k<=min(j,k2);k++) dp[i][j][1]=(dp[i][j][1]+dp[i][j-k][0])%mod; 17 } 18 } 19 printf("%d\n",(dp[n1][n2][0]+dp[n1][n2][1])%mod); 20 return 0; 21 }
标签:src hid ++ 转移 amp c++ scan 状态转移方程 mod
原文地址:https://www.cnblogs.com/pandaking/p/9941538.html