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]的状态可以从同排上一个推来.

posted @ 2021-02-06 23:01  acmloser  阅读(80)  评论(0编辑  收藏  举报