hdu4804Campus Design

来源:互联网 发布:p51h战斗机数据 编辑:程序博客网 时间:2024/06/01 10:11

Campus Design

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


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
 

Source
2013ACM/ICPC亚洲区南京站现场赛——题目重现

题意:给你n*m的格子,让你容1*2和1*1两种格子铺满,只有1位置能铺,并且1*1格子至少用c个,最多用d个,问铺满的方案数

解题思路:此题是上一题的加强,只需多加一个状态表示1*1所用个数即可,同样将1*2的木块分为横放和竖放两中方法,加上不放及1*1的方法分别计算即可。
                    dp[i][s][k]表示当前这一m个格子组成的s这个状态,并且用了K个1*1的格子(ps:如果想更好的学习此类题目,建议大家看大白书p383上关于轮廓线dp的讲解)注意转移时应该满足的条件!!!!!

代码:
<pre name="code" class="cpp">#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define mod 1000000007int dp[2][1<<10][22];char ma[105][15];int m;void update(int t,int a,int b,int k1,int k2){    if(b&(1<<m))//转移是必须满足之前的已经被填满    dp[t][b^(1<<m)][k2]=(dp[t][b^(1<<m)][k2]%mod+dp[1-t][a][k1]%mod)%mod;}int main(){    int n,c,d;    while(scanf("%d%d%d%d",&n,&m,&c,&d)!=EOF)    {        int i,j,k,s;        for(i=0;i<n;i++)        scanf("%s",ma[i]);        int t=0;        memset(dp,0,sizeof(dp));        dp[0][(1<<m)-1][0]=1;        for(i=0;i<n;i++)        {            for(j=0;j<m;j++)            {                t=1-t;                memset(dp[t],0,sizeof(dp[t]));                if(ma[i][j]=='1')                {                    for(k=0;k<=d;k++)                    {                        for(s=0;s<(1<<m);s++)                        {                            if(!dp[1-t][s][k])continue;                            update(t,s,(s<<1)^1,k,k+1);//放1*1                            update(t,s,s<<1,k,k);//不放                            if(j&&(!(s&1)))                            update(t,s,(s<<1)^3,k,k);//横放1*2                            if(i&&(!(s&(1<<m-1))))                            update(t,s,(s<<1)^1^(1<<m),k,k);//竖放1*2                        }                    }                }                else                {                    for(k=0;k<=d;k++)                    {                        for(s=0;s<(1<<m);s++)                        {                            if(!dp[1-t][s][k])continue;                            update(t,s,(s<<1)^1,k,k);//相当于放1*1,想一想为什么?                        }                    }                }            }        }        int ans=0;        for(i=c;i<=d;i++)        {            ans=(ans%mod+dp[t][(1<<m)-1][i]%mod)%mod;        }        printf("%d\n",ans);    }    return 0;}



0 0