Problem Description
Nanjing University of Science and Technology is celebrating its 60th anniversary. In order to make room for student activities, to make the university a more pleasant place for learning, and to beautify the campus, the college administrator decided to start construction on an open space.
The designers measured the open space and come to a conclusion that the open space is a rectangle with a length of n meters and a width of m meters. Then they split the open space into n x m squares. To make it more beautiful, the designer 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. The number of 1 x 2 bricks is unlimited.
4. Some squares have a flowerbed on it, so it should not be covered by any brick. (We use 0 to represent a square with flowerbet and 1 to represent other squares)
Now the designers want to know how many ways are there to cover the open space, meeting the above requirements.
The designers measured the open space and come to a conclusion that the open space is a rectangle with a length of n meters and a width of m meters. Then they split the open space into n x m squares. To make it more beautiful, the designer 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. The number of 1 x 2 bricks is unlimited.
4. Some squares have a flowerbed on it, so it should not be covered by any brick. (We use 0 to represent a square with flowerbet and 1 to represent other squares)
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 N lines, 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.
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 N lines, 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 test case. Each line should contain an integers representing the answer to the problem (mod 10
9 + 7).
Sample Input
1 1 0 0 1 1 1 1 2 0 1 1 1 2 1 1 2 1 2 11 1 2 0 2 01 1 2 0 2 11 2 2 0 0 10 10 2 2 0 0 01 10 2 2 0 0 11 11 4 5 3 5 11111 11011 10101 11111
Sample Output
0 0 1 1 1 2 1 0 2 954
题意:
给定一个图,0是不能放的,然后现在有1X1和1X2方块,最后铺满该图,使得1X1使用次数在C到D之间,1X2次数随便,问有几种放法
思路:
原来的插头dp的情况上再考虑1*1的方块,对于数量的限定只要再加一维即可。
//
// main.cpp
// C
//
// Created by zc on 2017/9/9.
// Copyright © 2017年 zc. All rights reserved.
//
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const ll MOD=1e9+7;
int n,m,C,D;
ll dp[2][(1<<10)+5][21];
int color[110][11]; //DP数组(滚动数组循环利用)
ll solve()
{
memset(dp,0,sizeof(dp));
ll (*crt)[21]=dp[0],(*snext)[21]=dp[1];
crt[0][0] = 1;
for (int i = n - 1; i >= 0; i--){
for (int j = m - 1; j >= 0; j--){
for (int used = 0; used < 1 << m; used++){
for(int k=0;k<=D;k++){
if ((used >> j & 1) || color[i][j]){
//不需要在(i, j)放置砖块
snext[used][k] = crt[used & ~(1 << j)][k];
}
else{
//尝试2种放法
int res = 0;
//横着放
if (j + 1 < m && !(used >> (j + 1) & 1) && !color[i][j + 1]){
res += crt[used | 1 << (j + 1)][k];
}
//竖着放
if (i + 1 < n && !color[i + 1][j]){
res += crt[used | 1 << j][k];
}
snext[used][k] = res % MOD;
if(k>0)
{
snext[used][k]=(snext[used][k]+crt[used][k-1])%MOD;
}
}
}
}
swap(crt, snext);
}
}
ll sum=0;
for(int i=C;i<=D;i++)
sum=(sum+crt[0][i])%MOD;//cout<<sum<<endl;
return sum;
}
char s[110];
int main(int argc, const char * argv[]) {
while(~scanf("%d%d%d%d",&n,&m,&C,&D))
{
for(int i=0;i<n;i++)
{
scanf("%s",s);
for(int j=0;j<m;j++)
{
color[i][j]=1-s[j]+'0';
}
}
ll ans=(solve()+MOD)%MOD;
printf("%lld\n",ans);
}
}