POJ 1038 Bugs Integrated, Inc.(状压dp)

Bugs Integrated, Inc.

Time Limit: 15000MS   Memory Limit: 30000K
Total Submissions: 10944   Accepted: 4234
Case Time Limit: 5000MS

Description

Bugs Integrated, Inc. is a major manufacturer of advanced memory chips. They are launching production of a new six terabyte Q-RAM chip. Each chip consists of six unit squares arranged in a form of a 2*3 rectangle. The way Q-RAM chips are made is such that one takes a rectangular plate of silicon divided into N*M unit squares. Then all squares are tested carefully and the bad ones are marked with a black marker. 


Finally, the plate of silicon is cut into memory chips. Each chip consists of 2*3 (or 3*2) unit squares. Of course, no chip can contain any bad (marked) squares. It might not be possible to cut the plate so that every good unit square is a part of some memory chip. The corporation wants to waste as little good squares as possible. Therefore they would like to know how to cut the plate to make the maximum number of chips possible. 
Task 
You are given the dimensions of several silicon plates and a list of all bad unit squares for each plate. Your task is to write a program that computes for each plate the maximum number of chips that can be cut out of the plate.

Input

The first line of the input file consists of a single integer D (1 <= D <= 5), denoting the number of silicon plates. D blocks follow, each describing one silicon plate. The first line of each block contains three integers N (1 <= N <= 150), M (1 <= M <= 10), K (0 <= K <= MN) separated by single spaces. N is the length of the plate, M is its height and K is the number of bad squares in the plate. The following K lines contain a list of bad squares. Each line consists of two integers x and y (1 <= x <= N, 1 <= y <= M) ?coordinates of one bad square (the upper left square has coordinates [1, 1], the bottom right is [N,M]).

Output

For each plate in the input file output a single line containing the maximum number of memory chips that can be cut out of the plate.

Sample Input

2
6 6 5
1 4
4 6
2 2
3 6
6 4
6 5 4
3 3
6 1
6 2
6 4

Sample Output

3
4

题意:

给你一个n*m(n<=150,m<=10)的网格,k(k<=n*m)个网格有障碍物,求最多能放多少个2*3的矩形。

思路:

由于每一行的状态与前两行有关,但是直接用3维表示这一行、前两行的状态的话,数组开不了那么大。于是我们考虑进行三进制状压。

第j位 为0表示 这一行的第j个格子和下一行的第j个格子均为空

第j位 为1表示 这一行的第j个格子非空,下一行的第j个格子为空

第j位 为2表示 下一行的第j个格子非空(因为此时这一行的第j个格子是否空都对答案无影响了)

即可对于每一行用dfs进行相应的状态转移。

但是这题很恶心,卡内存,于是第一维(第i行)根据我们的状态表示来说,可以滚动掉。

也不能预处理每一个数第j位为01还是2,于是只能写函数将对应状态的每一位为01还是2计算出来。

注意状态的转移,不合法的状态要去掉。(初始状态只有一种)

代码:

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn=12;
const int maxm=59055;
int a[155][maxn],c[maxn];
int b[]={0,1,3,9,27,81,243,729,2187,6561,19683,59049};
int dp[2][maxm];
int nex[maxn],now[maxn];
int n,m,k;
int tmp,ans;
int cal(int c[])
{
    int sum=0;
    for(int i=1;i<=m;i++)
    sum+=c[i]*b[i];
    return sum;
}
void wri(int zt,int a[])
{
    for(int i=1;i<=m;i++)
    {
        a[i]=zt%3;
        zt/=3;
    }
}
void dfs(int i,int j,int num)
{
    if(j==m+1) return ;
    int nw=(i+1)&1,nxt=nw^1,sta=cal(nex);
    dp[nxt][sta]=max(dp[nxt][sta],dp[nw][cal(now)]);
    if(j+1<=m&&!nex[j]&&!nex[j+1]&&!now[j]&&!now[j+1])
    {
        nex[j]=nex[j+1]=2;
        int kk=cal(nex);
        dp[nxt][kk]=max(dp[nxt][kk],num+1);
        dfs(i,j+2,num+1);
        nex[j]=nex[j+1]=0;
    }

    if(j+2<=m&&!nex[j]&&!nex[j+1]&&!nex[j+2])
    {
        nex[j]=nex[j+1]=nex[j+2]=2;
        int kk=cal(nex);
        dp[nxt][kk]=max(dp[nxt][kk],num+1);
        dfs(i,j+3,num+1);
        nex[j]=nex[j+1]=nex[j+2]=0;
    }
    dfs(i,j+1,num);
}
void go()
{
    memset(dp,-1,sizeof(dp));
    memset(now,0,sizeof(now));
    memset(nex,0,sizeof(nex));
    for(int i=1;i<=m;i++)
    now[i]=a[1][i]+1;
    dp[1][cal(now)]=0;
    for(int i=2;i<=n;i++)
    {
        int nw=(i+1)&1,nxt=nw^1;
        memset(dp[nxt],-1,sizeof(dp[nxt]));
        for(int j=0;j<b[m+1];j++)
        if(dp[nw][j]!=-1){
            wri(j,now);
            for(int k=1;k<=m;k++)
            {
                if(a[i][k]) nex[k]=2;
                else nex[k]=max(0,now[k]-1);
            }
            dfs(i,1,dp[nw][j]);
        }
    }
    int ans=0;
    for(int i=0;i<b[m+1];i++)
    ans=max(ans,max(dp[0][i],dp[1][i]));
    printf("%d\n",ans);
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        memset(a,0,sizeof(a));
        for(int i=0;i<k;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            a[x][y]=1;
        }
        go();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/89219038