【bzoj1037】 ZJOI2008—生日聚會Party

http://www.lydsy.com/JudgeOnline/problem.php?id=1037 (題目鏈接)

題意:有n個boy和m個girl排成一排,求使得任意一段的boy個數girl個數的差不超過k的方案數。

Solution
  dp。
  對於一段確定的人,設爲A,那麼只有A的後綴中男孩與女孩個數之差和女孩與男孩個數之差的最大值纔會影響此次決策。如此便可以定義狀態f[i][j][k][l]表示一段人中共有i個男孩j個女孩,且這段人的後綴中男孩與女孩的個數之差最大值爲k,女孩與男孩的個數之差最大值爲l的方案總數。
  有一個問題:A的所有後綴中男孩的個數都小於女孩的個數,也就是說k的值可能爲負。然而這是不影響的。我們可以讓這些狀態統一k=0,這樣做不會錯因爲若女生個數不會偏多(k實際上已經是負數了)也不會偏少(還會有第四維的狀態l來制約)。對於後綴中男生個數始終少於女生個數的情況也是這樣。

代碼:

// bzoj1037
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define MOD 12345678
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
inline LL getint() {
    int f,x=0;char ch=getchar();
    while (ch<='0' || ch>'9') {if (ch=='-') f=-1;else f=1;ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int n,m,c,f[151][151][21][21];

int main() {
    scanf("%d%d%d",&n,&m,&c);
    f[0][0][0][0]=1;
    for (int i=0;i<=n;i++)
        for (int j=0;j<=m;j++)
            for (int k=0;k<=min(c,i);k++)
                for (int l=0;l<=min(c,j);l++) {
                    if (i<n && k<c) f[i+1][j][k+1][max(l-1,0)]=(f[i+1][j][k+1][max(l-1,0)]+f[i][j][k][l])%MOD;
                    if (j<m && l<c) f[i][j+1][max(k-1,0)][l+1]=(f[i][j+1][max(k-1,0)][l+1]+f[i][j][k][l])%MOD;
                }
    int ans=0;
    for (int i=0;i<=c;i++)
        for (int j=0;j<=c;j++)
            ans=(ans+f[n][m][i][j])%MOD;
    printf("%d",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章