bzoj4806: 炮

来源:互联网 发布:金石造价软件下载 编辑:程序博客网 时间:2024/05/01 18:32

传送门
题目条件为同行同列最多只有两个炮。
首先,有2个炮的列实质相同。1个的和0个的也类似。
得到状态f[i][j][k]前i行j列没放,k列放了1个的方案数。
枚举转移即可。

#include<cstring>#include<iostream>#include<cstdio>#include<algorithm>#include<cstdlib>#include<cmath>#define mo 999983using namespace std;int n,m,dp[105][105][105],c[105][3];int dfs(int x,int y,int z){    if (x>n) return 1;    if (dp[x][y][z]) return dp[x][y][z];    dp[x][y][z]=dfs(x+1,y,z);    if (y>1) dp[x][y][z]=(dp[x][y][z]+1ll*dfs(x+1,y-2,z+2)*c[y][2])%mo;    if (y>0) dp[x][y][z]=(dp[x][y][z]+1ll*dfs(x+1,y-1,z+1)*c[y][1])%mo;    if (z>1) dp[x][y][z]=(dp[x][y][z]+1ll*dfs(x+1,y,z-2)*c[z][2])%mo;    if (z>0) dp[x][y][z]=(dp[x][y][z]+1ll*dfs(x+1,y,z-1)*c[z][1])%mo;    if (y&&z) dp[x][y][z]=(dp[x][y][z]+1ll*dfs(x+1,y-1,z)*c[y][1]*c[z][1])%mo;    return dp[x][y][z];}int main(){    scanf("%d%d",&n,&m);    for (int i=0;i<=m;i++) c[i][0]=1;    for (int i=1;i<=m;i++) c[i][1]=i;    for (int i=2;i<=m;i++)        c[i][2]=(c[i-1][2]+c[i-1][1])%mo;    printf("%d\n",dfs(1,m,0)); } 
0 0
原创粉丝点击