POJ - 2279 Mr. Young's Picture Permutations

发现自己最简单的DP都不会。 今天开始补一下DP的部分。 希望不要再拖队友的后退了。

题意: 现在有n个人,n个人的身高分别为 1,2,3...n,现在要把他们排成k列,需要从每一行从左到右身高递增,每一列从前往后身高递增,求合法排序身高的方案数。

题解:f[a][b][c][d][e] 表示已经站了每一列站了a b c d e的方案数, 那么可见的是 当 a < lim[1]的时候  f[a][b][c][d][e] 的状态可以转移到 f[a+1][b][c][d][e] 的状态, 

当 b < lim[2] 且 a > b 的时候  f[a][b][c][d][e] 的状态可以转移到 f[a][b+1][c][d][e] 的状态。

其他情况以此类推。

 

注意的是 如果这个题目开 f[30][30][30][30][30] 的时候是会爆空间的所以需要开刚好的空间。

代码:

#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>

using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod =  (int)1e9+7;
const int N = 35;
LL ans[32][16][11][9][7];
int lim[N];
int main(){
    int n, m;
    while(~scanf("%d", &n) && n){
        memset(ans, 0, sizeof(ans));
        memset(lim, 0, sizeof(lim));
        for(int i = 1; i <= n; i++)
            scanf("%d", &lim[i]);
        ans[0][0][0][0][0] = 1;
        for(int a = 0; a <= lim[1]; ++a)
            for(int b = 0; b <= lim[2] && b <= a; ++b)
                for(int c = 0; c <= lim[3] && c <= b; ++c)
                    for(int d = 0; d <= lim[4] && d <= c; ++d)
                        for(int e = 0; e <= lim[5] && e <= d; ++e){
                            if(a < lim[1]) ans[a+1][b][c][d][e] += ans[a][b][c][d][e];
                            if(b < lim[2] && a > b) ans[a][b+1][c][d][e] += ans[a][b][c][d][e];
                            if(c < lim[3] && a > c && b > c) ans[a][b][c+1][d][e] += ans[a][b][c][d][e];
                            if(d < lim[4] && a > d && b > d && c > d) ans[a][b][c][d+1][e] += ans[a][b][c][d][e];
                            if(e < lim[5] && a > e && b > e && c > e && d > e) ans[a][b][c][d][e+1] += ans[a][b][c][d][e];
                    }
        printf("%lld\n", ans[lim[1]][lim[2]][lim[3]][lim[4]][lim[5]]);
    }
    return 0;
}
View Code

 

posted @ 2018-11-06 20:46  Schenker  阅读(242)  评论(0编辑  收藏  举报