题意
n个男生m个女生排成一排,要求任意一段男生和女生人数差不超过k,求排列方案数。(假设所有男生都一样,所有女生都一样)答案取模。
数据范围
$$n,m\leqslant150\ \ \ ;\ \ \ k\leqslant20$$
题解
数据这么小,一想就是DP,但没想到是四维的……
f[i][j][x][y]表示前i个人中有j个男生,且从后面起男生最多比女生多x个,女生最多比男生多y个。
f[i+1][j+1][x+1][max(y-1,0)]+=f[i][j][x][y];(队列最后加一男生)
f[i+1][j][max(x-1,0)][y]+=f[i][j][x][y];(队列最后加一女生)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| const int mod=12345678; int f[301][151][21][21]; int MAX(int x,int y) {if (x>y) return x; return y;} int main() { int n,m,k,ans=0; scanf("%d%d%d",&n,&m,&k); f[0][0][0][0]=1; for (int i=0;i<m+n;i++) for (int j=0;j<=n;j++) for (int x=0;x<=k;x++) for (int y=0;y<=k;y++) if (f[i][j][x][y]) { if (x+1<=k&&j+1<=n) f[i+1][j+1][x+1][MAX(y-1,0)]=(f[i+1][j+1][x+1][MAX(y-1,0)]+f[i][j][x][y])%mod; if (y+1<=k&&i-j+1<=m) f[i+1][j][MAX(x-1,0)][y+1]=(f[i+1][j][MAX(x-1,0)][y+1]+f[i][j][x][y])%mod; } for (int x=0;x<=k;x++) for (int y=0;y<=k;y++) ans=(ans+f[n+m][n][x][y])%mod; printf("%d",ans); return 0; }
|
