POJ 1084 Square Destroyer 【DLX】

题目来源:http://poj.org/problem?id=1084
在这里插入图片描述
★这题做了一上午,一直在找bug,难受哇


题意:

现在有一个由边长为1的火柴拼成的正方形,火柴id 从上到下从左到右 。如果现在拿走一些火柴,问 最少 还需要拿走多少火柴,使得这个图形 不包含正方形


思路:

我们将 所有的火柴看做舞蹈链的行,所有的正方形看做舞蹈链的列 ~那问题就很简单了。
但是在舞蹈链初始化之前还是有点小麻烦的,比如怎么判断 该火柴是这个正方形的一部分

bool judge(dd a,dd b)
{
    if(a.x1<b.x1||a.x2>b.x2||a.y1<b.y1||a.y2>b.y2) return 0;//外
    if(a.x1>b.x1&&a.x1<b.x2&&a.y1>b.y1&&a.y1<b.y2) return 0;//内
    if(a.x2>b.x1&&a.x2<b.x2&&a.y2>b.y1&&a.y2<b.y2) return 0;//内
    return 1;
}

然后注意要check一下,不然整个dance会陷入死循环~

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<vector>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
using namespace std;
const int N=1e4+5;
const int M=1e2+5;
const int mod=1e9+7;
const int inf=0x7fffffff;
const double eps=1e-8;
const int pi=acos(-1);
template<class T>
void read(T &x)
{
    char c;x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
struct dd
{
    int x1,x2,y1,y2;
    dd(){};
    dd(int xx1,int xx2,int yy1,int yy2):x1(xx1),x2(xx2),y1(yy1),y2(yy2){};

}edge[M],mat[M];
struct DLX
{
    int n,m,cnt,ans;
    int up[N],right[N],down[N],left[N],col[N];
    int head[M],sz[M];
    bool vis[M];
    void init(int nn,int mm)
    {
        n=nn; m=mm; ans=inf;
        for(int i=0;i<=m;i++){
            up[i]=down[i]=i;
            right[i]=i+1;
            left[i]=i-1;
            sz[i]=0;
        }
        right[m]=0; left[0]=m;
        cnt=m;
        for(int i=1;i<=n;i++) head[i]=-1;
    }
    void link(int r,int c)
    {
        ++cnt;
        col[cnt]=c;
        sz[c]++;
        up[cnt]=up[c];
        down[cnt]=c;
        down[up[c]]=cnt;
        up[c]=cnt;
        if(head[r]==-1) head[r]=right[cnt]=left[cnt]=cnt;
        else{
            int tmp=head[r];
            right[cnt]=tmp;
            left[cnt]=left[tmp];
            right[left[tmp]]=cnt;
            left[tmp]=cnt;
        }
    }
    void check()
    {
//        cout<<m<<'x'<<endl;
        for(int i=1;i<=m;i++){
            if(!sz[i]){
//                cout<<i<<endl;
                right[left[i]]=right[i];
                left[right[i]]=left[i];
            }
        }
    }
    void del(int c)
    {
        for(int i=down[c];i!=c;i=down[i]){
            right[left[i]]=right[i];
            left[right[i]]=left[i];
        }
    }
    void res(int c)
    {
        for(int i=down[c];i!=c;i=down[i]){
            right[left[i]]=left[right[i]]=i;
        }
    }
    int f()
    {
        int sum=0;
        for(int i=right[0];i!=0;i=right[i]) vis[i]=1;
        for(int i=right[0];i!=0;i=right[i]){
            if(vis[i]){
                sum++;
                vis[i]=0;
                for(int j=down[i];j!=i;j=down[j]){
                    for(int l=right[j];l!=j;l=right[l]){
                        vis[col[l]]=0;
                    }
                }
            }
        }
        return sum;
    }
    void dance(int dep)
    {
        if(dep+f()>=ans) return ;
        if(right[0]==0){ans=dep; return ;}
        int now=right[0];
//        cout<<now<<endl;
        for(int i=now;i!=0;i=right[i]){
            if(sz[i]<sz[now]) now=i;
        }
        for(int i=down[now];i!=now;i=down[i]){
            del(i);
            for(int j=right[i];j!=i;j=right[j]) del(j);
            dance(dep+1);
            for(int j=right[i];j!=i;j=right[j]) res(j);
            res(i);
        }
    }
}dlx;
bool visedge[M],vismat[M];
bool judge(dd a,dd b)
{
    if(a.x1<b.x1||a.x2>b.x2||a.y1<b.y1||a.y2>b.y2) return 0;//外
    if(a.x1>b.x1&&a.x1<b.x2&&a.y1>b.y1&&a.y1<b.y2) return 0;//内
    if(a.x2>b.x1&&a.x2<b.x2&&a.y2>b.y1&&a.y2<b.y2) return 0;
    return 1;
}
int main()
{
    int t; read(t);
    while(t--){
        int n; read(n);
        int tot; read(tot);
        int pn=0,pm=0;
        for(int i=1;i<=n+1;i++){
            for(int j=1;j<=n;j++) edge[++pn]=dd(i,i,j,j+1);
            for(int j=1;j<=n+1;j++) if(i<=n) edge[++pn]=dd(i,i+1,j,j);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                for(int k=1;k<=n;k++){
                    if(i+k<=n+1&&j+k<=n+1) mat[++pm]=dd(i,i+k,j,j+k);
                }
            }
        }
        memset(visedge,0,sizeof visedge);
        memset(vismat,0,sizeof vismat);
        while(tot--){
            int a; read(a);
            visedge[a]=1;
            for(int i=1;i<=pm;i++){
                if(!vismat[i]){
                    if(judge(edge[a],mat[i]))
                        vismat[i]=1;
                }
            }
        }
        dlx.init(pn,pm);
        int sum=0;
        for(int i=1;i<=pn;i++) if(!visedge[i]){
            for(int j=1;j<=pm;j++) if(!vismat[j]){
                if(judge(edge[i],mat[j])){
                    dlx.link(i,j);
                    sum++;
                }
            }
        }
        dlx.check();
        dlx.dance(0);
        cout<<dlx.ans<<endl;
    }
    return 0;
}

发布了71 篇原创文章 · 获赞 89 · 访问量 8541

猜你喜欢

转载自blog.csdn.net/weixin_43890662/article/details/102817835
今日推荐