HDU 2861 —— Stools(DP)

来源:互联网 发布:.net微信js支付 编辑:程序博客网 时间:2024/05/21 07:13

题目:http://acm.hdu.edu.cn/showproblem.php?pid=2861

题目意思很好懂,这里就不解释了。

这种排列的组合数学问题,尤其是每个位置的状态不多的情况,这里每个位置就是坐了人跟没坐两种,大多是可以用DP解决的。

对于这个题目,定义状态dp[i][j][k][l],

表示前i个座位坐了j个人,形成k个块,l为0表示第i个座位不坐人,1则表示有人坐。

那么递推i+1的时候就只需要考虑第i+1个位置和第i个位置的状态,状态转移方程:

dp[i+1][j][k][0] += dp[i][j][k][0] //第i个位置木有人,第i+1个位置也木有人

dp[i+1][j+1][k][1] += dp[i][j][k][1] //第i个位置有人,第i+1个位置也有人

dp[i+1][j][k][0] += dp[i][j][k-1][1] //第i个位置有人,第i+1个位置木有人

dp[i+1][j+1][k][1] += dp[i][j][k-1][0] //第i个位置木有人,第i+1个位置有人

然后对于输入的n, m, k

答案就是dp[n][m][k][0]+dp[n][m][k][1]

dp数组先预处理全部算完,不然会T。。。

根据数据范围n,m<=200,k<=20,总状态数就是200*200*20*2 = 1.6 * 10^6

#include<cstdio>#include<cstring>typedef unsigned long long LL;LL dp[210][210][21][2];int n, m, i, j, k;int main(){    memset(dp,0,sizeof(dp));    dp[1][0][1][0]=dp[1][1][1][1]=1;    for(i=1; i<200; i++){        for(j=0; j<=i; j++){            for(k=0; k<=20; k++){                dp[i+1][j][k][0] += dp[i][j][k][0];                dp[i+1][j+1][k][1] += dp[i][j][k][1];                if(k){                    dp[i+1][j][k][0] += dp[i][j][k-1][1];                    dp[i+1][j+1][k][1] += dp[i][j][k-1][0];                }            }        }    }    while(~scanf("%d %d %d", &n, &m, &k)){        printf("%I64u\n", dp[n][m][k][0]+dp[n][m][k][1]);    }    return 0;}



0 0
原创粉丝点击