hdu6787(骰子+往回推的传输带问通过方案,dp)
题:http://acm.hdu.edu.cn/showproblem.php?pid=6787
题意:有1~n标号的格子,上面有m个传输带(传送带传的位置要传到之前去,1位置不能有格子)1~11的骰子,问有多少种安传输带的方案使得仍有可能从1到n(到n不动),期间位置不能超过n
分析:可以发现,只要不要连续安传输带的个数不大于10,则有可能从1到n,决策就是要不要在当前位置安传输带;
设dp[i][j][k],表示在位置 i 用了 j 个传输带 从i开始连续有k个传输带的方案数,那么dp[i][j][k]就是由dp[i-1][j-1][k-1]*(i-1)得来的,其中*(i-1)代表在位置 i 装传输带可以传到的范围为[1,n-1] ,n-1种可能;
k最多为10,在dp过程种累加即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int M=1e3+3; const int mod=1e9+7; int dp[M][M][13]; void init(){ dp[2][0][0]=1; for(int i=2;i<=1000;i++) for(int j=0;j<=1000;j++) for(int k=0;k<=10;k++){ dp[i+1][j+1][k+1]=(dp[i+1][j+1][k+1]+1ll*(i-1)*dp[i][j][k])%mod; dp[i+1][j][0]=(dp[i+1][j][0]+dp[i][j][k])%mod; } } int main(){ init(); int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d%d",&n,&m); if(m>max(0,n-2)){puts("-1");} else if(n<3){ puts("1"); } else printf("%d\n",dp[n+1][m][0]==0?-1:dp[n+1][m][0]); } return 0; }