Corn Fields POJ - 3254 (状压dp)
题目链接:
Corn Fields
题目大意:给你一个n*m的矩阵,矩阵的元素只包括0和1,0代表当前的位置不能放置人,1代表当前的位置可以放人,当你决定放人的时候,这个人的四个方向都不能放人,然后问你一共有多少种放置方式。
具体思路:二进制枚举,每一次判断和上下左右位置是否冲突就好了。
AC代码:
1 #include<iostream>
2 #include<stdio.h>
3 #include<cmath>
4 #include<string>
5 #include<cstring>
6 #include<algorithm>
7 using namespace std;
8 # define ll long long
9 # define inf 0x3f3f3f3f
10 const int maxn = 5e3+100;
11 const int mod = 1e9;
12 int dp[20][maxn];
13 int a[20][20];
14 int n,m;
15 bool check(int t1,int t2)
16 {
17 if((((t2<<1)&t2)==0)&&(((t2>>1)&t2)==0))
18 {
19 for(int j=0; j<m; j++){
20 if(((t2&(1<<j))&&a[t1][j])||(!(t2&(1<<j))))
21 continue;
22 else
23 return false;
24 }
25 return true;
26 }
27 else
28 return false;
29 }
30 int main()
31 {
32 scanf("%d %d",&n,&m);
33 for(int i=0; i<n; i++)
34 {
35 for(int j=0; j<m; j++)
36 {
37 scanf("%d",&a[i][j]);
38 }
39 }
40 int maxstate=(1<<m)-1;
41 for(int i=0; i<n; i++)
42 {
43 if(i==0)
44 {
45 for(int j=0; j<=maxstate; j++)
46 {
47 if(check(i,j))
48 dp[i][j]++;
49 }
50 }
51 else
52 {
53 for(int j=0; j<=maxstate; j++)
54 {
55 for(int k=0; k<=maxstate; k++)
56 {
57 if(check(i,k)&&((j&k)==0))
58 {
59 dp[i][k]+=dp[i-1][j];
60 }
61 }
62 }
63 }
64 }
65 // for(int i=0;i<=maxstate;i++){
66 // cout<<i<<" "<<dp[0][i]<<endl;
67 // }
68 ll sum=0;
69 for(int i=0; i<=maxstate; i++)
70 {
71 sum=(sum+dp[n-1][i])%mod;
72 }
73 printf("%lld\n",sum);
74 return 0;
75 }