POJ 2537 Tight words DP
简单DP
题意:由0-k这些数字组成的长度为n的数(并满足某个条件)的个数占所有总数的比例。
(满足某个条件:各个位的数字与其相邻的数字之差不超过1.)
用数组dp[i][j]表示满足以j结尾,长度为i的数的个数;
则适当思考可以得
状态转移方程为 : dp[i][j]=dp[i-1][j-1]+dp[i-1][j]+dp[j+1]; (0<j<k) dp[i][j]=dp[i-1][j]+dp[i-1][j+1]; (j==0) dp[i][j]=dp[i-1][j]+dp[i][j-1]; (j==k)
这里要考虑是不是边界
AC代码
View Code
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; int main() { int n, k, i, j; double dp[102][11]; while(~scanf("%d%d",&k,&n)) { for(i=0;i<=k;i++) dp[1][i]=1; for(i=2;i<=n;i++) { for(j=0;j<=k;j++) if(j==0)dp[i][j]=dp[i-1][j]+dp[i-1][j+1]; else if(j==k)dp[i][j]=dp[i-1][j]+dp[i-1][j-1]; else dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+dp[i-1][j+1]; } double s=0; for(i=0;i<=k;i++) s+=dp[n][i]; printf("%.5f\n",s*100/pow(k+1.0,n)); } return 0; }
写成3个实在麻烦,把0-k都虚拟地加1,初始化时把所有dp[][]的值清零,进行代码复杂度优化
状态转移方程为 : dp[i][j]=dp[i-1][j-1]+dp[i-1][j]+dp[j+1]; (1<=j<=k+1)
AC代码
View Code
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; int main() { int n, k, i, j; double dp[103][11]; while(~scanf("%d%d",&k,&n)) { memset(dp,0,sizeof(dp)); for(i=1;i<=k+1;i++) dp[1][i]=1; for(i=2;i<=n;i++) { for(j=1;j<=k+1;j++) dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+dp[i-1][j+1]; } double s=0; for(i=1;i<=k+1;i++) s+=dp[n][i]; printf("%.5f\n",s*100/pow(k+1.0,n)); } return 0; }
心得:DP需要多加练习,有些DP是不难的,不要被DP吓到了。
以后遇到这类边界问题适当转换一下就可以降低代码复杂度。


浙公网安备 33010602011771号