hdu 1400 Mondriaan's Dream 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1400

题目意思:给出一个h * w的 大 矩形,需要用 1 * 2 的砖块去填充这个大矩形,问填充的方案数是多少。

      这题参考这里的:

  http://www.informatik.uni-ulm.de/acm/Locals/2000/solution/dream.c

      把每一列的方格压缩为二进制编码,搜索上一列到当前列的状态转化是否能够成功。对于每一个位置,有3种放置方法:竖直、水平、不放

      对每个方格,1表示填充砖块,0表示没有填充砖块。将一层的状态存放在一个二进制数中。

     1、利用dfs,计算第一层的填充状态

     2、从第 1 层向第 n 层,利用DP 递推结果。

     变量from 和 to 的最大值,是宽为W的方格中都填充1,即(1<<W)-1,或者2^W-1

     初始时,假设第 0 层都填充1,只有一种情况。

     使用数组dp 表示每一层的递推关系,递推公式:

     令:from[j] = state[j] [0],       to[j] = state[j] [1],0 ≤ j < nstate

     则dp[i+1] [to[j]] =        ∑            dp[i] [from[j]], 0 ≤ j < nstate,  0 ≤ i < H

                              0 ≤  j < nstate

      最近都是抄人代码的节奏= =,哎~~~~,继续努力吧!!!

     

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 double dp[13][2100];   // 存放各层的递推结果(当宽为11时,2^11-1 = 2047,开2100即可)
 8 int state[14000][2];    // 保存状态转化的结果
 9 int H, W, nstate;
10 
11 // n: 当前从左往右数第n个方格,from:前n个方格在这一层编码, to:下一层的编码
12 // from 和 to的二进制长度与大长方形的宽度W是一致的
13 void dfs(int n, int from, int to)
14 {
15     if (n > W)
16         return;
17     // 整个宽度W填充完毕
18     if (n == W)
19     {
20         // 保存当前的状态转化
21         state[nstate][0] = from;
22         state[nstate++][1] = to;
23         return;
24     }
25     // 放置砖块的3种状态
26     // 水平放置砖块
27     dfs(n+2, (from<<2)+3, (to<<2)+3);     // 这个地方的+3, 后面的+1 不知道它想干嘛。希望有能之士可以指点指点
28     // 竖直放置砖块
29     dfs(n+1, (from<<1)+1, to<<1);
30     // 不放置
31     dfs(n+1, from<<1, (to<<1)+1);
32 }
33 
34 void DP()
35 {
36     memset(dp, 0, sizeof(dp));
37     // 第0层都填充1,只有一种情况
38     dp[0][(1<<W)-1] = 1;
39     for (int i = 0; i < H; i++)
40     {
41         for (int j = 0; j < nstate; j++)
42             dp[i+1][state[j][1]] += dp[i][state[j][0]];
43     }
44 }
45 
46 int main()
47 {
48     while (scanf("%d%d", &H, &W) != EOF && (H+W))
49     {
50         if (H < W)
51             swap(H, W);
52         nstate = 0;
53         dfs(0, 0, 0);
54         DP();
55         printf("%.0f
", dp[H][(1<<W)-1]);
56     }
57 }
原文地址:https://www.cnblogs.com/windysai/p/3897253.html