• 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 }
  • 相关阅读:
    opencv学习笔记7 重映射和仿射变换
    opencv学习笔记8 高斯金字塔,拉普拉斯金字塔,调整大小
    opencv学习笔记6 角点检测
    opencv学习笔记5 霍夫变换 漫水填充
    opencv学习笔记4 边缘检测
    opencv学习笔记3 滤波 形态学
    opencv学习笔记2 拖动条,亮度对比度 颜色空间缩减 鼠标事件
    opencv学习笔记1 加载图像 图像融合 分通道与合并
    URL编码表
    BUUCTF-[GWCTF 2019]我有一个数据库 1
  • 原文地址:https://www.cnblogs.com/windysai/p/3897253.html
Copyright © 2020-2023  润新知