POJ 1038 Bugs Integrated, Inc.

题目链接

题目大意:你有一个大小为 n m ( n 150 , m 10 ) 的矩形,其中有一些格子是不能选择的,现在问最多能从中完整的取出几个 2 3 (可旋转)的矩形。

思路:看到 n , m 相差如此之大,很容易让人浮想联翩。所以想到状压。
但是考虑状态。 2 3 的片片,在竖着摆放的时候,我们肯定需要知道他上面两行的状态,所以行被占用的情况就采用三进制状压(据说四进制状压会比较好写但是浪费空间)。

定义状态: f [ i ] [ S ] 表示前 i 行,第 i 行的状态是 S 下最多能取出几个矩形。
其中 S 的每一位分别有如下含义

  • 0:上一行和上上一行都是空的。
  • 1:上一行是空的,上上行被占用。
  • 2:上一行被占用(上上行不管,因为上一行被占用,无论当前怎么摆放都与上上行无关)。

考虑转移,枚举行和上一行的状态,通过DFS,枚举这里横着还是竖着放这还是不放这个块即可。

滚动数组,不然MLE。记得清空数组。

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<map>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<cctype>
#define pa pair<int,int>
#define INF 0x3f3f3f3f
#define inf 0x3f
#define fi first
#define se second
#define mp make_pair
#define ll long long
#define ull unsigned long long
#define pb push_back

using namespace std;

inline ll read()
{
    long long f=1,sum=0;
    char c=getchar();
    while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}
    while (isdigit(c)) {sum=sum*10+c-'0';c=getchar();}
    return sum*f;
}
#define MAXN 160
#define MAXM 100010
int f[2][MAXM],a[MAXN][MAXN],P[MAXN],n,m;
int S[2][15];
int getS(int tmp[])
{
    int ans=0;
    for (int i=0;i<m;i++) 
        ans+=tmp[i]*P[i];
    return ans;
}
void backS(int S,int tmp[])
{
    for (int i=0;i<m;i++)
        tmp[i]=S%3,S/=3;
}
int now,last;
void dfs(int i,int num,int St)
{
    if (i>=m) return ;
    if (i+2<m && !S[1][i] && !S[1][i+1] && !S[1][i+2])
    {
        S[1][i+1]=S[1][i]=S[1][i+2]=2;
        int s=getS(S[1]);
        f[now][s]=max(f[now][s],num+1);
        dfs(i+3,num+1,s);
        S[1][i]=S[1][i+1]=S[1][i+2]=0;
    }
    if (i+1<m && !S[1][i] && !S[1][i+1] && !S[0][i] && !S[0][i+1])
    {
        S[1][i]=S[1][i+1]=2;
        int s=getS(S[1]);
        f[now][s]=max(f[now][s],num+1);
        dfs(i+2,num+1,s);
        S[1][i]=S[1][i+1]=0;
    }
    f[now][St]=max(f[now][St],f[last][getS(S[0])]);
    dfs(i+1,num,St);
}
int main()
{
    int T;
    scanf("%d",&T);
    P[0]=1;
    for (int i=1;i<=14;i++)
        P[i]=P[i-1]*3;
    while (T--)
    {
        memset(a,0,sizeof(a));
        int num;
        scanf("%d%d%d",&n,&m,&num);
        for (int i=1;i<=num;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            a[--x][--y]=1;
        }
        memset(f,-1,sizeof(f));
        for (int i=0;i<m;i++)
            S[1][i]=a[0][i]?2:1;
        f[0][getS(S[1])]=0;
        last=1,now=0;
        for (int i=1;i<n;i++)
        {
            last^=1,now^=1;
            memset(f[now],-1,sizeof(f[now]));
            for (int state=0;state<P[m];state++)
            {
                if (f[last][state]==-1) continue;
                backS(state,S[0]);
                for (int j=0;j<m;j++)
                    S[1][j]=a[i][j]?2:(!S[0][j]?0:S[0][j]-1);
                dfs(0,f[last][state],getS(S[1]));
            }
        }
        int ans=0;
        for (int i=0;i<P[m];i++)
            ans=max(ans,f[now][i]);
        cout<<ans<<endl;    
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/szh_0808/article/details/80884167