生日Party 玄学多维DP

题目描述

今天是hidadz小朋友的生日,她邀请了许多朋友来参加她的生日party。 hidadz带着朋友们来到花园中,打算坐成一排玩游戏。为了游戏不至于无聊,就座的方案应满足如下条件:对于任意连续的一段,男孩与女孩的数目之差不超过k。很快,小朋友便找到了一种方案坐了下来开始游戏。hidadz的好朋友Susie发现,这样的就座方案其实是很多的,所以大家很快就找到了一种,那么到底有多少种呢?热爱数学的hidadz和她的朋友们开始思考这个问题…… 假设参加party的人中共有n个男孩与m个女孩,你是否能解答Susie和hidadz的疑问呢?由于这个数目可能很多,他们只想知道这个数目除以12345678的余数。
仅包含一行共3个整数,分别为男孩数目n, 女孩数目m, 常数k。
应包含一行,为题中要求的答案。
样例输入
1 2 1
样例输出
1

分析

  这个题想都不用想一看就是DP,但状态怎么找呢,可以确定的是,男孩和女孩的人数一定占两个状态,因为这个是可以确定他们的方案数的,剩下的我想维护男生与女生之间的差值,但这样显然是会出问题的,假如差值为2,那么有可能男生比女生多2,有可能女生比男生多2,这是两个方案,而这么定义状态的话就会出现少算方案数的情况,所以我们必须要维护男生比女生多的人数,女生比男生多的人数,这样状态就有了,定义dp[a][b][c][d]为共有a个女孩,b个男孩,男孩比女孩多c,女孩比男孩多d,那么每放一个人,就有两种可能,男生或女生,转移两次即可。

 1 #include<iostream>
 2 #define g dp[i][j][c][d]
 3 #define mod 12345678
 4 using namespace std;
 5 int dp[160][160][25][25];
 6 int main(){
 7     int n,m,k;
 8     cin>>n>>m>>k;
 9     dp[0][0][0][0]=1;
10     for(int i=0;i<=m;i++)
11     for(int j=0;j<=n;j++)
12     for(int c=0;c<=k;c++)
13     for(int d=0;d<=k;d++){
14         dp[i][j+1][c+1][max(d-1,0)]=(dp[i][j+1][c+1][max(d-1,0)]+g)%mod;
15         dp[i+1][j][max(c-1,0)][d+1]=(dp[i+1][j][max(c-1,0)][d+1]+g)%mod;
16     }
17     int ans=0;
18     for(int i=0;i<=k;i++)
19         for(int j=0;j<=k;j++)
20             ans=(ans+dp[m][n][i][j])%mod;
21     cout<<ans<<endl;
22 }
原文地址:https://www.cnblogs.com/anyixing-fly/p/12612690.html