Mondriaan's Dream POJ - 2411 (状压DP)

题目链接:

Mondriaan's Dream

 POJ - 2411 

题目大意:就是给你一个n*m的矩阵,然后问你用2*1的矩阵和1*2的矩阵,有多少种方法能凑出来n*m的矩阵,在不会有重叠的前提下。

具体思路:状压dp,对于1*2的矩阵,我们将这个方块构成的两块都标记为1;对于2*1的矩阵,我们将上面那个方块标记为1,下面那个方块标记为0.然后在具体判断的过程中,先判断第一行,

011是合法的,01是非法的。。。就是1只能是相邻的为偶数个。然后接下来的若干行按位判断,当(i,j)为0,(i-1,j)为0的时候,这种时候是非法的。当(i,j)为0,(i-1,j)为1的时候,这种时候是合法。

当(i,j)为1,(i-1,j)为0的时候,这种时候是合法的。当(i,j)为1,(i-1,j)为1的时候,并且(i,j+1)和(i-1,j+1)都为1,是合法的。前三种情况都右跳一个,最后一种情况右跳两个。

具体的学习网址:https://blog.csdn.net/hopeztm/article/details/7841917

AC代码:

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<string>
 6 using namespace std;
 7 # define inf 0x3f3f3f3f
 8 # define ll long long
 9 const int maxn = 2e5 +100;
10 const int N = (1ll<<11);
11 ll dp[12][N],n,m;
12 bool check(ll j)
13 {
14     ll i=0;
15     while(i<m)
16     {
17         if (( (1ll<<i) & j ) == 0 )
18             i++;
19         else if(i == m-1 || ((j & (1ll<<(i+1ll))) ==0))
20         {
21             return false;
22         }
23         else
24         {
25             i+=2;
26         }
27     }
28     return true;
29 }
30 bool judge(int pos_state,int head_state)
31 {
32     int i=m-1;
33     while(i>=0)
34     {
35         int pos1=(pos_state&(1<<i));
36         int pos2=(head_state&(1<<i));
37         if(!pos1&&!pos2){return false;}
38         if(!pos1&&pos2){i--;continue;}
39         if(pos1&&!pos2){i--;continue;}
40         if((i-1)>=0&&pos1&&pos2&&(pos_state&(1<<(i-1)))&&(head_state&(1<<(i-1)))){i-=2;continue;}
41         return false;
42     }
43     return true;
44 }
45 int main()
46 {
47     while(~scanf("%lld %lld",&n,&m)&&(n+m))
48     {
49         memset(dp,0,sizeof(dp));
50         if(m>n)
51             swap(n,m);
52         ll maxstate=(1ll<<m)-1;
53         for(ll j=0; j<=maxstate; j++)
54         {
55             if(check(j))
56             {
57                 dp[0][j]=1;
58             }
59         }
60         for(ll i=1; i<n; i++)
61         {
62             for(ll j=0 ; j <= maxstate ; j++)
63             {
64                 for(ll k=0; k <= maxstate ; k++)
65                 {
66                     if(judge(j,k))
67                     {
68                         dp[i][j]+=dp[i-1][k];
69                     }
70                 }
71             }
72         }
73         printf("%lld\n",dp[n-1][maxstate]);
74     }
75     return 0;
76 }

猜你喜欢

转载自www.cnblogs.com/letlifestop/p/10821460.html