比较简单的DP,关键是设计好状态。
使用f[i][j][p1][p2]表示前i个小孩中有j个男孩,且男孩比女孩多p1个,女孩比男孩多p2个的方案数
根据当前状态累加之后的状态
转移方程:f[i+1][j+1][p1+1][p2-1] = ∑f[i][j][p1][p2],f[i+1][j][p1-1][p2+1] = ∑f[i][j][p1][p2]
由于根据当前状态累加之后的状态,所以要从0开始递推。
注意好边界情况就行了。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mo = 12345678;
const int maxn = 152;
const int maxk = 22;
int f[2][maxn][maxk][maxk];
int n,b,g,k;
void init()
{
freopen("bzoj1037.in","r",stdin);
freopen("bzoj1037.out","w",stdout);
}
void add(int &a,int b)
{
a += b;
if(a >= mo)a -= mo;
}
void readdata()
{
scanf("%d%d%d",&b,&g,&k);
n = b + g;
}
void solve()
{
memset(f,0,sizeof(f));
int now = 0,las = 1;
f[0][0][0][0] = 1;
for(int i = 0;i < n;i++)
{
swap(now,las);
memset(f[now],0,sizeof(f[now]));
for(int j = 0;j <= min(i,b);j++)
{
for(int p1 = 0;p1 <= min(j,k);p1++)
{
for(int p2 = 0;p2 <= min((i - j),k);p2++)
{
int tmp = f[las][j][p1][p2];
if(p1 < k && j < b)add(f[now][j+1][p1+1][max(p2-1,0)],tmp);
if(p2 < k && (i - j) < g)add(f[now][j][max(p1-1,0)][p2+1],tmp);
}
}
}
}
int ans = 0;
for(int p1 = 0;p1 <= k;p1++)
for(int p2 = 0;p2 <= k;p2++)
add(ans,f[now][b][p1][p2]);
printf("%d\n",ans);
}
int main()
{
init();
readdata();
solve();
return 0;
}