hdu6787(骰子+往回推的傳輸帶問通過方案,dp)
阿新 • • 發佈:2020-07-27
題: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過程種累加即可
#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[iView Code+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; }