hdu 4804 Campus Design (状压dp)

Campus Design

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


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
2013ACM/ICPC亚洲区南京站现场赛——题目重现


题意:
用1*2,1*1的方块去地板,地板标0的位置不能铺,问用1*1的地板在[c,d]区间内铺的方法数。

思路:
状压dp,可以先去做这题,poj 2411 dp加一维表示1*1方块的个数就够了。

代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 101
#define MAXN 10005
#define mod 1000000007
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 0.000001
typedef long long ll;
using namespace std;

ll n,m,ans,cnt,tot,flag;
ll c,d;
char mp[maxn][15];
ll dp[maxn][1<<11][21];

void dfs(ll row,ll col,ll s1,ll s2,ll num1,ll num2)
{
 //   printf("row:%I64d col:%I64d s1:%I64d s2:%I64d num1:%I64d num2:%I64d\n",row,col,s1,s2,num1,num2);
    if(num2>d) return ;
    if(col==m)
    {
        dp[row+1][s2][num2]+=dp[row][s1][num1];
        dp[row+1][s2][num2]%=mod;
        return ;
    }
    if(mp[row][col]=='1')
    {
        dfs(row,col+1,s1,s2&~(1<<col),num1,num2);
        return ;
    }
    ll i,j,t;
    if(s1&(1<<col))
    {
        dfs(row,col+1,s1,s2&~(1<<col),num1,num2);  // 1->0
    }
    else
    {
        if(mp[row+1][col]!='1') dfs(row,col+1,s1,s2|(1<<col),num1,num2);  // 0->1
        dfs(row,col+1,s1,s2&~(1<<col),num1,num2+1);  // 0->1 num2++
        if(col+1<m&&!(s1&(1<<col+1))&&mp[row][col+1]!='1')  // 00->00
        {
            ll s=s2&~(1<<col);
            s=s&~(1<<col+1);
            dfs(row,col+2,s1,s,num1,num2);
        }
    }
}
void solve()
{
    ll i,j,k,t;
    for(i=0;i<=n;i++)
    {
        for(j=0;j<tot;j++)
        {
            for(k=0;k<=d;k++)
            {
                dp[i][j][k]=0;
            }
        }
    }
    dp[0][0][0]=1;
    for(i=0;i<n;i++)
    {
        for(j=0;j<tot;j++)
        {
            for(k=0;k<=d;k++)
            {
                if(dp[i][j][k]>0) dfs(i,0,j,0,k,k);
            }
        }
    }
    ans=0;
    for(i=c;i<=d;i++)
    {
 //       printf("i:%I64d dp:%I64d\n",i,dp[n][0][i]);
        ans+=dp[n][0][i];
        ans%=mod;
    }
}
int main()
{
    ll i,j,t;
    while(~scanf("%I64d%I64d%I64d%I64d",&n,&m,&c,&d))
    {
        for(i=0;i<n;i++)
        {
            scanf("%s",mp[i]);
            for(j=0;j<m;j++)
            {
                if(mp[i][j]=='1') mp[i][j]='0';
                else mp[i][j]='1';
            }
        }
        tot=1<<m;
        solve();
        printf("%I64d\n",ans);
    }
    return 0;
}
/*
2 4 0 0
1111
1111

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



 

你可能感兴趣的:(hdu 4804 Campus Design (状压dp))