Mr. Young's Picture Permutations POJ - 2279
考察:线性DP
本蒟蒻是完全没想到这个方程...思路基本照搬Y总
思路:
可以从题目分析出两个性质:
1.第i行人数一定>=第i+1行.(因为每列都要求递减)
2.每一行人数只能从左开始相邻放
行数最多5,可以考虑每行一个状态.设f[i][j][k][t][p]设置为第一行有i个人,第二行有j个人....以此类推,在动规中我们常以最后一步干什么而分类.由上面的性质二,我们可以最后一个人在第x行分类,当确定他在第x行时,该行人数-1的方案数与不减1时相同.由此可得状态转移方程
注意:只有第i排的人数>第i+1排,此状态才存在.
并且数据
5
6 5 4 3 2 答案就已经9位数了,因此开Long Long
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 const int N = 35; 7 typedef long long ll; 8 ll f[N][N][N][N][N]; 9 int a[6]; 10 int main() 11 { 12 int n; 13 while(scanf("%d",&n)!=EOF&&n) 14 { 15 memset(a,0,sizeof a); 16 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 17 f[0][0][0][0][0] = 1; 18 for(int i=0;i<=a[1];i++) 19 for(int j=0;j<=a[2]&&j<=i;j++) 20 for(int k=0;k<=a[3]&&k<=j;k++) 21 for(int t=0;t<=a[4]&&t<=k;t++) 22 for(int p=0;p<=a[5]&&p<=t;p++) 23 { 24 if(i||j||k||t||p) f[i][j][k][t][p] = 0; 25 if(i&&i-1>=j) f[i][j][k][t][p]+=f[i-1][j][k][t][p]; 26 if(j&&j-1>=k) f[i][j][k][t][p]+=f[i][j-1][k][t][p]; 27 if(k&&k-1>=t) f[i][j][k][t][p]+=f[i][j][k-1][t][p]; 28 if(t&&t-1>=p) f[i][j][k][t][p]+=f[i][j][k][t-1][p]; 29 if(p) f[i][j][k][t][p]+=f[i][j][k][t][p-1]; 30 } 31 printf("%lld\n",f[a[1]][a[2]][a[3]][a[4]][a[5]]); 32 } 33 return 0; 34 }
总结:
1.多写
2.线性DP不要只局限在二维
3.考虑状态的成立条件
这道题没有样例本蒟蒻是不知道开long long的,不知道咋算的,网上的题解也没有写的.....
2021.3.12 二刷 没想出来,最多考虑到f[i][j]表示第i排第j列放人的方案数,然后划分不出集合....
这道题为什么是线性dp,因为相邻数字只能放在相邻位置.我们从小到大放数字,连续数字只能相邻放,f[i][j][k][q][m]的状态可以从同排上一个推来.