UVA11270 Tiling Dominoes —— 插头DP

题目链接:https://vjudge.net/problem/UVA-11270

 

 

 

 

 

题意:

用2*1的骨牌填满n*m大小的棋盘,问有多少种放置方式。

 

题解:

骨牌类的插头DP。

1.由于只需要记录轮廓线上m个位置的放置情况(0或1),且m<=10,2^10 = 1024,故可以用二进制对轮廓线的信息进行压缩。

2.二进制中,第0为代表着当前轮廓线位于第0列的位置的放置情况,以此类推。

3.具体情况分析,设当前格子为a[i][j]:

1) 不放置:前提条件为上面的位置a[i-1][j]已经放置了骨牌。原因:如果上面的位置为空,且这次又不放,那么往后就没有机会填补这个空缺了。

2) 往上放:前提条件为上面的位置a[i-1][j]没有放置骨牌。原因显而易见。

3) 往左放:前提条件为上面的位置a[i-1][j]放置了骨牌,且左边的位置a[i][j-1]没有放置骨牌。原因:情况1)和情况2)的综合。

 

 

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <cmath>
 7 #include <queue>
 8 #include <stack>
 9 #include <map>
10 #include <string>
11 #include <set>
12 using namespace std;
13 typedef long long LL;
14 const int INF = 2e9;
15 const LL LNF = 9e18;
16 const int MOD = 1e9+7;
17 const int MAXN = 11;
18 
19 int n, m, cur;
20 LL dp[2][1<<MAXN];
21 
22 int main()
23 {
24     while(scanf("%d%d", &n,&m)!=EOF)
25     {
26         if(n<m) swap(n, m);
27         memset(dp, 0, sizeof(dp));
28 
29         cur = 0;
30         dp[0][(1<<m)-1] = 1;    //初始状态,第一个格子的轮廓线上都有插头,所以就防止了往外放
31         for(int i = 0; i<n; i++)
32         for(int j = 0; j<m; j++)
33         {
34             cur ^= 1;
35             memset(dp[cur], 0, sizeof(dp[cur]));
36             for(int s = 0; s<(1<<m); s++)   //由于有m个插头,而插头的编号从0开始,故最大状态为(1<<m)-1。
37             {
38                 //枚举的是上一个格子的所有状态,即当前格子的轮廓线
39                 int up = 1<<j;  //位于第j列的插头,即上插头
40                 int left = 1<<(j-1);  //位于第j-1列的插头, 即左插头
41                 bool hav_up = s&up;
42                 bool hav_left = s&left;
43                 if( hav_up )  //不放置,前提是上插头存在
44                     dp[cur][s^up] += dp[cur^1][s];
45 
46                 if( i!=0 && !hav_up)   //往上边放,前提是上插头不存在
47                     dp[cur][s^up] += dp[cur^1][s];
48 
49                 if( j!=0 && hav_up && !hav_left ) //往左边放,前提是上插头存在且左插头不存在
50                     dp[cur][s^left] += dp[cur^1][s];
51             }
52         }
53 
54         printf("%lld\n", dp[cur][(1<<m)-1]);
55     }
56 }
View Code

 

posted on 2017-12-04 21:21  h_z_cong  阅读(363)  评论(0编辑  收藏  举报

导航