jzoj P1667 【AHOI2009】中国象棋

来源:互联网 发布:js object clone 编辑:程序博客网 时间:2024/05/16 16:57

题目大意:
在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。求有多少种放置方法?由于值比较大,输出其mod 9999973的结果。
中国象棋中炮的行走方式大家应该很清楚吧。

100%的数据中N,M不超过100
50%的数据中,N,M至少有一个数不超过8
30%的数据中,N,M均不超过6

题解:
DP:
题目可以发现,每一列最多放2个炮,所以可以做动规:
f[i,j,k]表示前i行j列放1个棋,k列放2个棋子的最大值。
所以对于到f[i,j,k]有6个情况:
1.不放棋子丨f[i-1][j][k]
2.放一个棋子,放在之前没有棋子的一列丨f[i-1][j-1][k]*(m-j-k+1)
3.放一个棋子,放在之前有一个棋子的一列丨f[i-1][j+1][k-1]*(j+1);
4.放两个棋子,放在之前没有棋子的两列丨f[i-1][j-2][k]*C(m-j-k+2)
5.放两个棋子,都放在之前没有棋子的一列丨f[i-1][j][k-1]*(m-j-k+1)*j
6.放两个棋子,分别放在之前没有棋子和有一个棋子的两列丨f[i-1][j+2][k-2]*C(j+2)
C的操作是x*(x-1) div 2,这是某个很神奇的组合数操作….

var     f:array [-10..101,-10..101,-10..101] of longint;     ans,n,m,i,j,k:longint;function c(a:longint):longint;begin      exit(a*(a-1) div 2);end;begin     readln(n,m);     f[0,0,0]:=1;     for i:=1 to n do         for j:=0 to m do             for k:=0 to m-j do                 begin                       f[i,j,k]:=(f[i-1,j,k]+                                  f[i-1,j-1,k]*(m-j-k+1)+                                  f[i-1,j+1,k-1]*(j+1)+                                  f[i-1,j-2,k]*c(m-j-k+2)+                                  f[i-1,j,k-1]*(m-j-k+1)*j+                                  f[i-1,j+2,k-2]*c(j+2)) mod 9999973;                 end;     for i:=0 to m do         for j:=0 to m-i do             ans:=(ans+f[n,i,j]) mod 9999973;     writeln(ans);end.
2 0
原创粉丝点击