Campus Design
Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 763 Accepted Submission(s): 364
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
N*M的格子,1*2的砖有无限个,1*1的砖必须放[C,D]之间个,有些地方不能放砖,有多少种方法。
比前面那题稍微有点改动,多设一维,表示目前使用的1*1的个数。注意状态转移,如果这格子是空的,放1*1的时候就花费1个1*1的,如果这个格子本来就不能放,就相当于放1*1的但是不花费1*1的砖。状态s为到当前格子(包括当前格子)最近的M的格子的状态,1是被覆盖,0是没覆盖,离的远的是高位。
这题要用滚动数组的方法,要不会超内存。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN=110;
const int MAXM=20010;
const LL MOD=1e9+7;
int N,M,C,D;
char a[110][15];
LL dp[2][22][(1<<11)+10];
int main(){
freopen("in.txt","r",stdin);
while(scanf("%d%d%d%d",&N,&M,&C,&D)!=EOF){
for(int i=1;i<=N;i++) scanf("%s",a[i]+1);
memset(dp,0,sizeof(dp));
int cur=0;
dp[cur][0][(1<<M)-1]=1;
for(int i=1;i<=N;i++)
for(int j=1;j<=M;j++){
cur=!cur;
memset(dp[cur],0,sizeof(dp[cur]));
for(int k=0;k<=D;k++)
for(int s=0;s<(1<<M);s++){
if(a[i][j]=='1'){
if(s&1){
dp[cur][k][s]=(dp[cur][k][s]+dp[1-cur][k][s>>1])%MOD; //放2*1
if(j>1&&(s&2)) dp[cur][k][s]=(dp[cur][k][s]+dp[1-cur][k][(s>>1)^(1<<(M-1))^1])%MOD; //放1*2
if(k>0) dp[cur][k][s]=(dp[cur][k][s]+dp[1-cur][k-1][(s>>1)^(1<<(M-1))])%MOD; //放1*1
}
else{
dp[cur][k][s]=(dp[cur][k][s]+dp[1-cur][k][(s>>1)^(1<<(M-1))])%MOD; //不放
}
}
else{
if(s&1) dp[cur][k][s]=(dp[cur][k][s]+dp[1-cur][k][(s>>1)^(1<<(M-1))])%MOD;
else dp[cur][k][s]=0;
}
}
}
LL ans=0;
for(int i=C;i<=D;i++) ans=(ans+dp[cur][i][(1<<M)-1])%MOD;
printf("%I64d\n",ans);
}
return 0;
}