HDU 4804 Campus Design 轮廓线DP

原题

Description

Nanjing University of Scienceand Technology is celebrating its 60th anniversary. In order to make room forstudent activities, to make the university a more pleasant place for learning,and to beautify the campus, the college administrator decided to startconstruction on an open space.
The designers measured the open space and come to a conclusion that the openspace is a rectangle with a length of n meters and a width of m meters. Thenthey split the open space into n x m squares. To make it more beautiful, thedesigner decides to cover the open space with 1 x 1 bricks and 1 x 2 bricks,according to the following rules:

1. All the bricks can be placed horizontally or vertically
2. The vertexes of the bricks should be placed on integer lattice points
3. The number of 1 x 1 bricks shouldn’t be less than C or more than D. Thenumber of 1 x 2 bricks is unlimited.
4. Some squares have a flowerbed on it, so it should not be covered by anybrick. (We use 0 to represent a square with flowerbet and 1 to represent othersquares)

Now the designers want to know how many ways are there to cover the open space,meeting the above requirements.

 

Input

There are several test cases,please process till EOF.
Each test case starts with a line containing four integers N(1 <= N <=100), M(1 <= M <= 10), C, D(1 <= C <= D <= 20). Then following Nlines, each being a string with the length of M. The string consists of ‘0’ and‘1’ only, where ‘0’ means the square should not be covered by any brick, and‘1’ otherwise.

 

Output

Please print one line per testcase. Each line should contain an integers representing the answer to theproblem (mod 10 9 + 7).

大意

给一个大平面矩形格子,格子标号为0的不防砖,1的放砖,砖有1x11x2两种,其中1x1的只能使用C~D个,1x2无限制,输出方案数。

思路

    这是一道典型的轮廓线动态规划的贴砖块问题。

    状态上记录轮廓上每个格子的放置情况。这是因为每个放置最多影响到下一行和旁边一个格子,所以只要记录边缘的状态就可以了,记录轮廓而不是每行的状态是为了按格子递推的时候方便处理。没格只记录是否放,用01表示压缩成一个二进制数。如果记录放哪种砖,后面再把1*1的合并,则会出现叠加部分分不清的尴尬局面。

    递推的方式采取按一格一格的递推,每一格只修改当前所对应的状态位,如果横放1*2的则修改左边的状态位。虽然每一格后状态所表示的格子不同了,但这并不会让状态相互重叠。因为在每次递推到下一格的时候即滚动数组,状态也就统一到新轮廓下的各种方案数。

    这一类动态规划比插头的要简单许多,我觉得可以都归结为轮廓形,插头是轮廓状态记录是否有伸出去。推荐陈丹琦女神的经典论文《基于连通性状态压缩的动态规划问题》。

代码 C

#include <stdio.h>
#include <string.h>

#define MOD 1000000007

long long dp[2][1024][22];

int main()
{
    int n, m, c, d, i, j, k, s, cur;
    char squre[12];
    while(scanf("%d%d%d%d", &n, &m, &c, &d) > 0)
    {
        memset(dp, 0, sizeof dp);
        dp[cur=0][(1<<m)-1][0] = 1;
        for(i=0; i<n; i++)
        {
            scanf("%s", squre);
            for(j=0; j<m; j++)
            {
                cur ^= 1;
                memset(dp[cur], 0, sizeof dp[cur]);
                for(k=1<<m; k--;)
                    for(s=0; s<=d; s++)
                    {
                        if(squre[j] == '1')
                        {
                            if(k & 1 << j)
                            {
                                dp[cur][k][s+1] = (dp[cur][k][s+1] + dp[cur^1][k][s]) % MOD;
                                dp[cur][k^1<<j][s] = (dp[cur][k^1<<j][s] + dp[cur^1][k][s]) % MOD;
                                if(j && !(k&1<<j-1))
                                    dp[cur][k^1<<j-1][s] = (dp[cur][k^1<<j-1][s] + dp[cur^1][k][s]) % MOD;
                            }
                            else
                                dp[cur][k^1<<j][s] = (dp[cur][k^1<<j][s] + dp[cur^1][k][s]) % MOD;
                        }
                        else if (k & 1 << j)
                        {
                            dp[cur][k][s] = (dp[cur][k][s] + dp[cur^1][k][s]) % MOD;
                        }
                    }
            }
        }
        for(i=c, s=0; i<=d; i++)
            s = (s + dp[cur][(1<<m)-1][i]) % MOD;
        printf("%d\n", s);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值