传送门:CodeVS1255
这道题很显然是DP
第一个求方案应该是很白痴的DP
三维数组就可以了
用$ f_{i,j,k} $记录自上而下第i层当前层用了j个一共用了k个(注意这里j<=10)
转移就是
$f_{i,j,k}=f_{i-1,j-1,k-j}+f_{i-1,j+1,k-j}$
这里的主要问题就在于为什么要自上而下统计
因为第二问求具体方案时要按照自下而上的字典序输出,所以要保证下面状态的比上面的大,成为一棵树(二叉树),然后就可以求解方案了
代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; long long n,h,m,ans,x,p,q,s; long long f[80][30][1000]; int main(){ scanf("%lld%lld%lld",&n,&h,&m); for (int i=1;i<=10;i++) f[1][i][i]=1; for (int i=2;i<=h;i++) for (int j=1;j<=10;j++) for (int k=1;k<=n;k++) f[i][j][k]=f[i-1][j-1][k-j]+f[i-1][j+1][k-j]; printf("%lld\n",f[h][m][n]); while (1){ scanf("%lld",&x); if (x==-1) break; p=m; q=h; s=n; while (q){ printf("%lld ",p); if (x<=f[q-1][p-1][s-p]){ s-=p; q--; p--; } else{ x-=f[q-1][p-1][s-p]; s-=p; q--; p++; } } printf("\n"); } return 0; }
|