天天看点

poj 1038 Bugs Integrated, Inc.

poj 1038 Bugs Integrated, Inc.

题目抽象;给你一个n*m个矩阵,芯片的大小事2*3的,其中有些方格是坏掉的,不能放置芯片,而且芯片不能重叠放置,问这样的矩阵最多能够放几个芯片;

这个采用dp+dfs。把每一行看成是是一个整体,第y行的芯片放置受y-1行和y-2行情况的影响。如果第y行被标记为黑色则State[y]=2,如果y行未被标记而y-1行被标记则state[y]=1,如果y和y-1行均未被标记则state[y]=0,同样方法求出state[y-1],:用3进制来存放每个格子的状态,根据上一行的状态用dfs来搜索当前行的允许的所有状态。

这题还是看别人的代码和思路弄出来的

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;
int n,m,k;
int bad[151][11];
int dp[2][60000];
int stateA[11],stateB[11];
int fact3[11];

void getFact3()
{
    int i;
    for(i=1,fact3[0]=1;i<11;i++)
     fact3[i]=fact3[i-1]*3;
}
int getState(int f[])
{
    int tmp=0,i;
    for(i=1;i<=10;i++)
     tmp+=f[i]*fact3[i-1];
    return tmp;
}
void backState(int s,int f[])
{
    for(int i=1;i<=10;i++)
    {
        f[i]=s%3;
        s/=3;
    }
}
void init()
{
    memset(dp[1],-1,sizeof(dp[1]));
    memset(stateA,0,sizeof(stateA));
    for(int i=1;i<=m;i++)  //开始我把m写成了10,结果调试了半天
     stateA[i]=bad[1][i]+1;
   dp[1][getState(stateA)]=0;
}
inline int max(int a,int b)
{
    return a>b?a:b;
}
void dfs(int x,int i,int ct,int state)
{
    int now;
    if(i>=m) return;
    if(i<=m-2&&stateA[i]==0&&stateA[i+1]==0&&stateA[i+2]==0) //横放
    {
        stateA[i]=stateA[i+1]=stateA[i+2]=2;
        now=getState(stateA);
        dp[x % 2][now] = max(dp[x % 2][now],ct+1);
        dfs(x,i+3,ct+1,now);
        stateA[i]=stateA[i+1]=stateA[i+2]=0;
    }
    if (stateA[i] == 0 && stateA[i + 1] == 0 && stateB[i] == 0 && stateB[i + 1] == 0)  //竖着放
    {
         stateA[i] = stateA[i + 1] = 2;
         now=getState(stateA);
         dp[x%2][now]=max(dp[x%2][now],ct+1);
         dfs(x,i+2,ct+1,now);
         stateA[i] = stateA[i + 1] = 0;
    }
    dp[x%2][state]=max(dp[x%2][state],dp[(x+1)%2][getState(stateB)]);
    dfs(x,i+1,ct,state); //不放
}

void Dp()
{
    int i,j;
    for(i=2;i<=n;i++)
    {
        memset(dp[i%2],-1,sizeof(dp[i%2]));
        for(j=0;j<fact3[m];j++)
        {
            if(dp[(i+1)%2][j]!=-1)
            {
                backState(j,stateB);
                for(int k=1;k<=m;k++)
                 if(bad[i][k]==1)
                   stateA[k]=2;
                 else
                   {
                       stateA[k] = stateB[k] - 1;
                       if(stateA[k] < 0)
                         stateA[k] = 0;
                   }
                dfs(i,1,dp[(i+1)%2][j],getState(stateA));
            }
        }
    }
}
int solve()
{
    int ans=0,i;
    for(int i=0;i<fact3[m];i++)
     ans=max(ans,max(dp[0][i],dp[1][i]));
    return ans;
}
int main()
{
    int d,i;
    getFact3();
    cin>>d;
    for(i=0;i<d;i++)
    {
        cin>>n>>m>>k;
        int j,x,y;
        memset(bad,0,sizeof(bad));
        for(j=0;j<k;j++)
        {
            cin>>x>>y;
            bad[x][y]=1;
        }
        if(n<2) { puts("0");continue; }
        getFact3();
       // cout<< fact3[10]<<endl;
        init();
        Dp();
        printf("%d\n",solve());
    }
    return 0;
}