BZOJ1801: [Ahoi2009]chess 中国象棋

 

1801: [Ahoi2009]chess 中国象棋

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 765  Solved: 435
[Submit][Status]

Description

在N行M列的棋盘上,放若干个炮可以是0个,使得没有任何一个炮可以攻击另一个炮。 请问有多少种放置方法,中国像棋中炮的行走方式大家应该很清楚吧.

Input

一行包含两个整数N,M,中间用空格分开.

Output

输出所有的方案数,由于值比较大,输出其mod 9999973

Sample Input

1 3

Sample Output

7

HINT

除了在3个格子中都放满炮的的情况外,其它的都可以.

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

Source

Day2

题解:

Benz的题解:
其实我觉得这题很好。Dp。
50%的分数可以状态压缩拿到。
因为棋盘上没有障碍,所以其实状态只跟有多少列放了1个棋子,多少列放了2个有关,
而跟具体是哪几列无关。
那么就可以不用状态压缩了。
f[i][j][k]表示前i行,有j列放1个棋子,有k列放2个棋子的方案数。
转移时枚举这一行放0 1 或 2个棋子即可。
复杂度:O(n*m^2)。
用int64存,每个状态算完后再取模。

代码:

 1 #include<cstdio>
 2 
 3 #include<cstdlib>
 4 
 5 #include<cmath>
 6 
 7 #include<cstring>
 8 
 9 #include<algorithm>
10 
11 #include<iostream>
12 
13 #include<vector>
14 
15 #include<map>
16 
17 #include<set>
18 
19 #include<queue>
20 
21 #include<string>
22 
23 #define inf 1000000000
24 
25 #define maxn 105
26 
27 #define maxm 500+100
28 
29 #define eps 1e-10
30 
31 #define ll long long
32 
33 #define pa pair<int,int>
34 
35 #define for0(i,n) for(int i=0;i<=(n);i++)
36 
37 #define for1(i,n) for(int i=1;i<=(n);i++)
38 
39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
40 #define mod 9999973
41 
42 using namespace std;
43 
44 inline int read()
45 
46 {
47 
48     int x=0,f=1;char ch=getchar();
49 
50     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
51 
52     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
53 
54     return x*f;
55 
56 }
57 ll n,m,f[maxn][maxn][maxn];
58 inline int c(int x)
59 {
60     return x*(x-1)/2;
61 }    
62 
63 int main()
64 
65 {
66 
67     freopen("input.txt","r",stdin);
68 
69     freopen("output.txt","w",stdout);
70 
71     n=read();m=read();
72     f[0][0][0]=1;
73     for1(i,n)
74      for0(j,m)
75       for(int k=0;j+k<=m;k++)
76       {
77           f[i][j][k]=f[i-1][j][k];
78           if(j>0)f[i][j][k]+=f[i-1][j-1][k]*(m-j-k+1);
79           if(k>0)f[i][j][k]+=f[i-1][j+1][k-1]*(j+1);
80           if(k>1)f[i][j][k]+=f[i-1][j+2][k-2]*c(j+2);
81           if(k>0)f[i][j][k]+=f[i-1][j][k-1]*j*(m-j-k+1);
82           if(j>1)f[i][j][k]+=f[i-1][j-2][k]*c(m-j-k+2);      
83           if(f[i][j][k]>=mod)f[i][j][k]%=mod;     
84       }
85     ll ans=0;
86     for0(i,m)
87      for0(j,m)
88       ans+=f[n][i][j],ans%=mod;
89     printf("%lld\n",ans);       
90 
91     return 0;
92 
93 }
View Code

ll.。。。

 

posted @ 2014-09-10 13:11  ZYF-ZYF  Views(213)  Comments(0Edit  收藏  举报