标签:
题意:给你n个身高高低不同的士兵。问你把他们按照波浪状排列(高低高或低高低)有多少方法数。
析:这是一个DP题是很明显的,因为你暴力的话,一定会超时,应该在第15个时,就过不去了,所以这是一个DP计数问题。
那么我们应该怎么想呢,我们先假设前 i-1 个已经放好了,然后第 i 个一定是最高的,所以,他一定要在前面找一个低后面放上他,肯定不能放在高的后面,
那么状态就有的表示了,d[i][0]表示是以低结尾,d[i][1]是以高结尾,我们假设放第 i 个士兵时,前面有 j 个,那么后面就有 i - j - 1个,前面的乘以后面的,
再乘以 C[i-1][j],就是数量,那么怎么转移呢,就是这样,因为以低结尾和以高结尾,数量肯定是一样,所以,每人都是一半。
那么答案就出来了。再节约一点空间,就可以开成一维的。
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <algorithm> #include <vector> #include <map> #include <cctype> #include <stack> using namespace std; typedef long long LL; typedef pair<int, int> P; const int INF = 0x3f3f3f3f; const double inf = 0x3f3f3f3f3f3f; const LL LNF = 100000000000000000; const double PI = acos(-1.0); const double eps = 1e-8; const int maxn = 1e2 + 5; const int mod = 1e9 + 7; const char *mark = "+-*"; const int dr[] = {-1, 0, 1, 0}; const int dc[] = {0, 1, 0, -1}; int n, m; inline bool is_in(int r, int c){ return r >= 0 && r < n && c >= 0 && c < m; } inline LL Max(LL a, LL b){ return a < b ? b : a; } inline LL Min(LL a, LL b){ return a > b ? b : a; } inline int Max(int a, int b){ return a < b ? b : a; } inline int Min(int a, int b){ return a > b ? b : a; } LL C[25][25]; LL d[25]; void init(){ for(int i = 0; i < 25; ++i) C[i][0] = 1; for(int i = 1; i < 22; ++i) for(int j = 1; j <= i; ++j) C[i][j] = C[i-1][j] + C[i-1][j-1]; d[0] = d[1] = 1; for(int i = 2; i < 21; ++i){ LL ans = 0; for(int j = 0; j <= i; ++j) ans += d[j] * d[i-j-1] * C[i-1][j]; d[i] = ans/2; } } int main(){ init(); int T; cin >> T; while(T--){ scanf("%d %d", &m, &n); printf("%d ", m); if(1 == n) printf("1\n"); else printf("%I64d\n", d[n]<<1); } return 0; }
HDU 4489 The King’s Ups and Downs (DP+数学计数)
标签:
原文地址:http://www.cnblogs.com/dwtfukgv/p/5769284.html