HDU

来源:互联网 发布:mysql怎么查看表空间 编辑:程序博客网 时间:2024/06/03 18:29


Campus Design

                                                          Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                                                                  Total Submission(s): 1429    Accepted Submission(s): 740


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.
 

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.
 

Output
Please print one line per test case. Each line should contain an integers representing the answer to the problem (mod 109 + 7).
 

Sample Input
1 1 0 011 1 1 201 1 1 211 2 1 2111 2 0 2011 2 0 2112 2 0 010102 2 0 001102 2 0 011114 5 3 511111110111010111111
 

Sample Output
001112102954
 


思路:轮廓线上的DP。从(0,0)到(n-1,m-1),用d[now][k][num]表示在now这个点,k表示前m个格子的填放情况(注意:不是上一行的m个格子,是从当前格子开始,自右向左,自下而上的m个格子),那么有5种情况(注意:满足这5种情况的前提都是,当前格子的上面那个格子及之前的格子都要填满,因为以后无法再去填了),见代码。

#include<iostream>#include<cstdio>#include<cstring>using namespace std;long long mod=1e9+7;long long d[2][1<<10][30];char s[110][20];int main(){int n,m,MIN,MAX;while(cin>>n>>m>>MIN>>MAX){int now=0,nex=1;memset(d,0,sizeof d);for(int i=0;i<n;i++)scanf("%s",s[i]);d[now][(1<<m)-1][0]=1;for(int i=0;i<n;i++){for(int j=0;j<m;j++){for(int k=0;k<(1<<m);k++){if((1<<(m-1)&k)&&s[i][j]=='1')            //不放 且 以后状态能放 {for(int num=0;num<=MAX;num++){d[nex][(k<<1)^(1<<m)][num]+=d[now][k][num];d[nex][(k<<1)^(1<<m)][num]%=mod;}}if((1<<(m-1))&k)           //放1*1的方块 {if(s[i][j]=='1')    //当前格子可以放 {for(int num=0;num+1<=MAX;num++){d[nex][(1<<m)^(k<<1)^1][num+1]+=d[now][k][num];d[nex][(1<<m)^(k<<1)^1][num+1]%=mod;}}else            //当前格子不能放{for(int num=0;num<=MAX;num++){d[nex][(1<<m)^(k<<1)^1][num]+=d[now][k][num];d[nex][(1<<m)^(k<<1)^1][num]%=mod;}}}if(i&&(1<<(m-1)&k)==0&&s[i][j]=='1')    //放竖着的1*2的方块 且 前格子可以放  {for(int num=0;num<=MAX;num++){d[nex][(k<<1)^1][num]+=d[now][k][num];d[nex][(k<<1)^1][num]%=mod;}}if(j&&(k&1)==0&&(1<<(m-1)&k)&&s[i][j]=='1') //放横着的1*2的方块  且 前格子可以放  {for(int num=0;num<=MAX;num++){d[nex][(k<<1)^(1<<m)^3][num]+=d[now][k][num];d[nex][(k<<1)^(1<<m)^3][num]%=mod;}}}memset(d[now],0,sizeof d[now]);now^=1;nex^=1;}}long long ans=0;for(int i=MIN;i<=MAX;i++)ans+=d[now][(1<<m)-1][i],ans%=mod;cout<<ans<<endl;}return 0;}