BZOJ1037 ZJOI2008生日聚会(动态规划)
设f[i][j][x][y]为安排了i个男孩j个女孩,后缀最大男孩-女孩数为x,最大女孩-男孩数为y的方案数。转移显然。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 151 #define M 22 #define P 12345678 int n,m,k,f[N][N][M][M]; void inc(int &x,int y){x+=y;if (x>=P) x-=P;} int main() { #ifndef ONLINE_JUDGE freopen("bzoj1037.in","r",stdin); freopen("bzoj1037.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(),k=read(); f[0][0][0][0]=1; for (int i=1;i<=n+m;i++) for (int j=max(0,i-m);j<=min(n,i);j++) { int x=j,y=i-j; for (int p=0;p<=min(k,x);p++) for (int q=0;q<=min(k,y);q++) { if (x&&p) { inc(f[x][y][p][q],f[x-1][y][p-1][q+1]); if (q==0) inc(f[x][y][p][q],f[x-1][y][p-1][q]); } if (y&&q) { inc(f[x][y][p][q],f[x][y-1][p+1][q-1]); if (p==0) inc(f[x][y][p][q],f[x][y-1][p][q-1]); } } } int ans=0; for (int i=0;i<=k;i++) for (int j=0;j<=k;j++) inc(ans,f[n][m][i][j]); cout<<ans; return 0; }