发现自己最简单的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 ", ans[lim[1]][lim[2]][lim[3]][lim[4]][lim[5]]); } return 0; }