UVALive 6177|HDU 4489|The King's Ups and Downs|动态规划

来源:互联网 发布:ios开源app源码 编辑:程序博客网 时间:2024/05/16 14:12

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4188

题目翻译

国王有一些身高不同的守卫。他希望给这些守卫安排一个排列,但不是简单地按身高从矮到高或者从高到矮,而是波浪形(每个人总比相邻的两个人都高或都矮),比如:
160, 162, 164, 166, 168, 170, 172的两种可行排列是:
160, 164, 162, 168, 166, 172, 170或者
172, 160, 170, 162, 168, 164, 166

国王希望知道有多少种排列方式。为了方便表示,我们按1,2,表示身高从矮到高。
如果有4个守卫,那么有一下几种排列:
1324, 2143, 3142, 2314, 3412, 4231, 4132, 2413, 3241, 1423

计算有n个守卫时的排列方式有多少种。

输入

第一行一个整数P(1P1000),表示数据组数。接下来每组数据一行2个整数D,n(1n20),分别表示数据组编号和守卫的个数(身高总不相同)。

输出

对于每组数据输出一行2个整数D和排列数。

样例输入

41 12 33 44 20

样例输出

1 l2 43 104 740742376475050

题解

如果令fi,j表示排列的第i位为j,且i1位的数字小于j(我们只关心数字的相对大小),gi,j表示排列的第i位为j,且i1位的数字大于j。那么显然有:
fi,j=j1k=1fi1,k
gi,j=nk=j+1gi1,k
如果算完打个表就知道f和g是对称的(观察一下公式也可以)。
即:gi,j=fi,ij+1
就是说,如果原来一个序列为{ai},那么新的序列{n+1ai}的元素仍落在[1,n]内,但是相对的大小就与原序列相反。
于是我们有:

fi,j=k=1j1fi1,ik


fi,j1=k=1j2fi1,ik

所以有
fi,j=fi,j1+fi1,ij+1

也就是说,如果发现一层的dp只与上一层有关,不如考虑一下本层内有没有可以递推的公式。
然后。。结果就是
ansn=2ifn,i

(因为f表示的是最开始先增的情况,还有对称的最开始先减的情况)

// UVALive 6177, HDU 4489#include <cstdio>#define FOR(i,j,k) for(i=j;i<=k;++i)const int N = 21;long long dp[N][N], ans[N];int main() {    int T, kase, n, i, j;    dp[1][1] = 1;    ans[1] = 1;    FOR(i,2,20) FOR(j,2,i) {        dp[i][j] = dp[i - 1][i - j + 1] + dp[i][j - 1];        ans[i] += dp[i][j] * 2;    }    scanf("%d", &T);    while (T--) {        scanf("%d%d", &kase, &n);        printf("%d %lld\n", kase, ans[n]);    }    return 0;}
原创粉丝点击