poj 1038 Bugs Integrated,Inc.(状圧dp)


http://poj.org/problem?id=1038
Bugs Integrated、Inc.
Time Limit: 15000 MS
 
メモリLimit: 30000 K
Total Submissions: 8917
 
Acceepted: 3404
Case Time Limit: 5000 MS
Description
Bugs Integrated、Inc.is a majorr majurmamajurmamamamamajururof advanced memomorychips.They ararlaunching productctctctctctctio of a a a a new aaaaw six teraaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaartested carefullyand the bad ones are marked with a black maker. 
poj 1038 Bugs Integrated, Inc.(状压dp)_第1张图片
Finally,the play 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)スクウェア.It might not be possible to cut the plate so that everry good square is a part of some memory chip.The copopopopoports to waste good squares as possible.The fore thery would like the khocut 
Task 
You are given the dimensions of several silicon ples and a list of all bad unit squares for each plate.Your task is to write a program that computtes for each plate the maximnumber of chips ap.
Input
The first line of the input file consists of a single integer D(1<=D==5)、denoting the number of silicon pltes.D blocks follw、each describing one silicon plate.The first line of of each block block ininininininggggggggggs=1=1=1=rererererererererererererererererereres=1=1=1=1=1=s=1=1=s=1=s=s=s=rereininininininininininininininininininininininininininininaces.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 lineas 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 up per left square has coordination[1,1],the bottom right is[N,M])
Output
For each plate in the input file output a single line containing the maximnumber 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
ソurce
CEOI 2002
N*Mの矩形を一つあげます.この矩形には2*3の矩形がいくつあるかと聞きました.条件としては、悪い点があります.悪い点は矩形を入れてはいけません.
M<=10ですので、形圧が可能です.3進数の状態は圧縮して、2はこの点が放すことができないことを表して、1はこの点が置くことができることを表していますが、その前の点は置くことができなくて、0はこの点が置くことができることを表しています.しかもその前の点も置くことができます.この行の状態で後ろの行を押し出した状態で、まず矩形を置かない状態に対して、この行為2では次の行が1となり、この行為1では次の行が0となり、この行為が0なら次の行も0となります.次の行に置かない状態で、この行を矩形にした状態で、2つの0を連続して前の行に対応する位置も0ならば、縦に長方形を置いてもいいです.0を連続して3つ置くと、長方形を横に置くことができます.悪い点があるので、矩形に悪い点があるかどうかを判断します.長方形を置くすべての状態を検索して更新できます.複雑度O(n*m*3^m).状圧dpを移行する際に、dfsで有効状態を検索して更新するのも良い最適化手段です.コードは以下の通りです
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#define nn 110000
#define inff 0x3fffffff
typedef long long LL;
using namespace std;
int n,m,k;
bool huai[200][20];
bool hu[200][20][200][20];
int dp[2][60000];
int po[20];
int w1[20],w2[20];
int ans,t;
void fuck(int x)
{
    for(int i=0;i<m;i++)
    {
        printf("%d",x%3);
        x/=3;
    }
    puts("");
}
bool check(int x1,int y1,int x2,int y2)
{
    int i,j,g,e;
    for(i=x1;i<=x2;i++)
    {
        for(j=y1;j<=y2;j++)
        {
            if(huai[i][j])
                return true;
        }
    }
    return false;
}
void init()
{
    int i,j,g,e;
    po[0]=1;
    for(i=1;i<=m;i++)
        po[i]=po[i-1]*3;
    memset(hu,false,sizeof(hu));
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            for(g=i;g<=n;g++)
            {
                for(e=j;e<=m;e++)
                {
                    hu[i][j][g][e]=check(i,j,g,e);
                }
            }
        }
    }
    for(i=0;i<=1;i++)
    {
        for(j=0;j<po[m];j++)
            dp[i][j]=-1;
    }
    dp[0][po[m]-1]=0;
}
void dfs(int id,int zt,int fc,int h)
{
    if(id==m)
        return ;
    int ix;
    if(id<m-1&&w2[id]==0&&w2[id+1]==0)
    {
        if(w1[id]==0&&w1[id+1]==0)
        {
            if(!hu[h-1][id+1][h+1][id+2])
            {
                ix=zt+2*po[id]+2*po[id+1];
                dp[1-t][ix]=max(dp[1-t][ix],fc+1);
                dfs(id+2,ix,fc+1,h);
            }
        }
        if(id<m-2&&w2[id+2]==0)
        {
            if(!hu[h][id+1][h+1][id+3])
            {
                ix=zt+2*po[id]+2*po[id+1]+2*po[id+2];
                dp[1-t][ix]=max(dp[1-t][ix],fc+1);
                dfs(id+3,ix,fc+1,h);
            }
        }
    }
    dfs(id+1,zt,fc,h);
}
void solve()
{
    int i,j,g,e;
    int ix,tem,fc;
    t=0;
    for(i=0;i<n;i++)
    {
        for(j=0;j<po[m];j++)
        {
            if(dp[t][j]<0)
                continue;
            ix=j,tem=0;
            for(g=0;g<m;g++)
            {
                w1[g]=ix%3;
                ix/=3;
                if(w1[g]==0)
                    w2[g]=0;
                else
                    w2[g]=w1[g]-1;
                tem+=w2[g]*po[g];
            }
            dp[1-t][tem]=max(dp[1-t][tem],dp[t][j]);
            dfs(0,tem,dp[t][j],i);
        }
        memset(dp[t],-1,sizeof(t));
        t=1-t;
    }
    ans=0;
    for(i=0;i<po[m];i++)
    {
        ans=max(ans,dp[t][i]);
    }
}
int main()
{
    int d,i;
    scanf("%d",&d);
    while(d--)
    {
        scanf("%d%d%d",&n,&m,&k);
        int u,v;
        memset(huai,false,sizeof(huai));
        for(i=1;i<=k;i++)
        {
            scanf("%d%d",&u,&v);
            huai[u][v]=true;
        }
        init();
        solve();
        printf("%d
",ans); } return 0; }