hdu 4804 Campus Design 插头dp

Campus Design

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


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 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
 

Source
 

Recommend
liuyiding
 

题意:有1*1和1*2两种砖,0点不能铺砖,求用1*1砖数量在c到d的铺砖种类数。

思路:加一维表示用1*1砖的数量,注意特判m,n=1的情况。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1<<12;
const int mod=1e9+7;
int dp[2][N][25];
char vis[105][13];
int n,m,c,d;
int main()
{
    while(scanf("%d%d%d%d",&n,&m,&c,&d)!=EOF){
        for(int i=0;i<n;i++){
            getchar();
            scanf("%s",vis[i]);
        }
        if(n==1&&m==1){
            if(vis[0][0]=='1'&&c<=1&&d>=1)
             {
                printf("1\n");
                continue;
             }
            else {
                printf("0\n");
                continue;
            }
        }
        memset(dp,0,sizeof(dp));
        dp[0][0][0]=1;
        int pre=1,now=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                pre=!pre;
                now=!now;
                int q=1<<j;
                int p=q<<1;
                memset(dp[now],0,sizeof(dp[now]));
                for(int k=0;k<1<<(m+1);k++){
                    for(int l=0;l<=d;l++){
                        if(vis[i][j]=='1'){
                            if((k&p)&&!(k&q))
                                dp[now][k-p][l]=(dp[now][k-p][l]+dp[pre][k][l])%mod;
                            if(!(k&p)&&(k&q))
                                dp[now][k-q][l]=(dp[now][k-q][l]+dp[pre][k][l])%mod;
                            if(!(k&p)&&!(k&q)){
                                dp[now][k][l+1]=(dp[now][k][l+1]+dp[pre][k][l])%mod;
                                dp[now][k+p][l]=(dp[now][k+p][l]+dp[pre][k][l])%mod;
                                dp[now][k+q][l]=(dp[now][k+q][l]+dp[pre][k][l])%mod;
                            }
                        }
                        else if(!(k&p)&&!(k&q))
                            dp[now][k][l]=dp[pre][k][l];
                    }
                }
            }
            now=!now;
            pre=!pre;
            memset(dp[now],0,sizeof(dp[now]));
            for(int j=0;j<(1<<m);j++)
                for(int l=0;l<=d;l++){
                    dp[now][j<<1][l]=dp[pre][j][l];
                }
        }
        long long ans=0;
        for(int i=c;i<=d;i++)
            ans=(ans+dp[now][0][i])%mod;
        printf("%I64d\n",ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值