【POJ 1084】 很烦人的DLX

 

DLX。。。

一开始读错题目了。。。是要把所有正方形都消掉!!!

代码里面有两种统计正方形和火柴的方法,都值得借鉴。。Orz


发一下代码

 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int head=0;
const int INF=10000000;
const int maxn = 1000;
const int maxd = 10000;
int cnt, res;
int mat[maxn][maxn], s[maxn], l[maxd], r[maxd], u[maxd], d[maxd], c[maxd], o[maxn], row[maxd];
bool use[maxn];
void makegragh(int &n, int &m)
{
    memset(mat, 0, sizeof(mat));
//初始化mat矩阵
}
void initial(int n, int m)
{
    memset(use, false, sizeof(use));
    res=n+1;
    int i, j, rowh;
    memset(s, 0, sizeof(s));
    for(i=head; i<=m; i++)
    {
        r[i]=(i+1)%(m+1);
        l[i]=(i-1+m+1)%(m+1);
        u[i]=d[i]=i;
    }
    cnt=m+1;
    for(i=1; i<=n; i++)
    {
        rowh=-1;
        for(j=1; j<=m; j++)
        {
            //printf("%d", mat[i][j]);
            if(mat[i][j])
            {
                s[j]++;
                u[cnt]=u[j];
                d[u[j]]=cnt;
                u[j]=cnt;
                d[cnt]=j;
                row[cnt]=i;
                c[cnt]=j;
                if(rowh==-1)
                {
                    l[cnt]=r[cnt]=cnt;
                    rowh=cnt;
                }
                else
                {
                    l[cnt]=l[rowh];
                    r[l[rowh]]=cnt;
                    r[cnt]=rowh;
                    l[rowh]=cnt;
                }
                cnt++;
            }
        }
        //puts("");
    }
}
void remove(int c)
{
    for(int i=d[c]; i!=c; i=d[i])
    {
        r[l[i]]=r[i];
        l[r[i]]=l[i];
    }
}
void resume(int c)
{
    for(int i=d[c]; i!=c; i=d[i])
        r[l[i]]=l[r[i]]=i;
}
int h()
{
    bool has[maxn];
    memset(has, false, sizeof(has));
    int ans=0;
    for(int i=r[head]; i!=head; i=r[i])
        if(!has[i])
        {
            ans++;
            for(int j=d[i]; j!=i; j=d[j])
                for(int k=r[j]; k!=j; k=r[k])
                    has[c[k]]=true;
        }
    return ans;
}
bool dfs(int k)
{
    if(k+h()>=res)return false;//A* cut

    if(r[head]==head)
    {
        if(k<res) res=k;
        return true;
    }
    int ms=INF, cur=0;
    for(int t=r[head]; t!=head; t=r[t])
        if(s[t]<ms)
        {
            ms=s[t];
            cur=t;
        }
    for(int i=d[cur]; i!=cur; i=d[i])
    {
//        int rr = (row[i] - 1) / 2 + 1;
//        if (!use[rr]) use[rr] = true;
//        else continue;
        remove(i);
        for(int j=r[i]; j!=i; j=r[j])
        {
            remove(j);
            s[c[j]]--;
        }
        dfs(k+1);
        for(int j=l[i]; j!=i; j=l[j])
        {
            resume(j);
            s[c[j]]++;
        }
//        use[rr] = false;
        resume(i);
    }
    return false;
}
const int N=10;
int stick[2*N*(N+1)+N][N*N];/*
void makestick(int n)
{
     for (int i=1;i<=2*n*(n+1);++i)
     {
         if (i<=n) 
         {
            stick[i][0]=1;
            stick[i][1]=i;
         }
         else if (i>=2*n*(n+1)-n+1)
         {
               stick[i][0]=1;
               stick[i][1]=n*n-2*n*(n+1)+i;
         }
         else if (i % (2*n+1)==n+1)
         {
               stick[i][0]=1;
               stick[i][1]=((i)/(2*n+1))*n+1;
         }
         else if (i % (2*n+1)==0)
         {
               stick[i][0]=1;
               stick[i][1]=(i/(2*n+1))*n;
         }
         
         else if (i % (2*n+1)>n+1)
         {
              stick[i][0]=2;
              stick[i][1]=(i/(2*n+1))*n+i%(2*n+1)-n-1;
              stick[i][2]=(i/(2*n+1))*n+i%(2*n+1)-n;
         }
         else
         {
             stick[i][0]=2;
             stick[i][1]=(i/(2*n+1)-1)*n+i%(2*n+1);
             stick[i][2]=(i/(2*n+1)-1)*n+i%(2*n+1)+n;
         }
     }/*
     for (int i=1;i<=2*n*(n+1);++i)
     {
         printf("%d--%d:",i,stick[i][0]);
         for (int j=1;j<=stick[i][0];++j)
             printf(" %d",stick[i][j]);
         printf("\n");
     }
}
*/
int NumOfSq;
void makestick(int n)
{
     memset(stick,0,sizeof(stick));
     NumOfSq=0;int ss;
     for (int c=1;c<=n;++c)
     {
         for (int i=1;i<=n-c+1;++i)
         {
             for (int j=1;j<=n-c+1;++j)
             {
                 ++NumOfSq;
                 
                 //Up
                 ss=(i-1)*(2*n+1)+j;
                 for (int p=0;p<c;++p)
                 {
                     ++stick[ss+p][0];
                     stick[ss+p][stick[ss+p][0]]=NumOfSq;
                 }
                 
                 //Left
                 ss=(i-1)*(2*n+1)+j+n;
                 for (int p=0;p<c;++p)
                 {
                     stick[ss+p*(2*n+1)][++stick[ss+p*(2*n+1)][0]]=NumOfSq;
                 }
                 
                 //Right
                 ss=(i-1)*(2*n+1)+j+c+n;
                 for (int p=0;p<c;++p)
                 {
                     stick[ss+p*(2*n+1)][++stick[ss+p*(2*n+1)][0]]=NumOfSq;
                 }
                 
                 //Down
                 ss=(i-1+c)*(2*n+1)+j;
                 for (int p=0;p<c;++p)
                 {
                     stick[ss+p][++stick[ss+p][0]]=NumOfSq;
                 }
             }
         }
     }
     /*
     for (int i=1;i<=2*n*(n+1);++i)
     {
         printf("%d--%d:",i,stick[i][0]);
         for (int j=1;j<=stick[i][0];++j)
             printf(" %d",stick[i][j]);
         printf("\n");
     }
     */
}
int n,m,M;
bool lstsq[N*N*2+N];
bool lststick[2*N*(N+1)+N];
int sq[N*N*2+N];
int sqnum[N*N*2+N];
int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
          memset(sqnum,0,sizeof(sqnum));
          memset(mat,0,sizeof(mat));
          memset(lstsq,0,sizeof(lstsq));
          memset(lststick,0,sizeof(lststick));
          memset(sq,0,sizeof(sq));
          scanf("%d%d",&n,&m);
          makestick(n);
          int rline;
          while (m--)
          {
                int st;
                scanf("%d",&st);
                lststick[st]=1;
                for (int i=1;i<=stick[st][0];++i)
                    lstsq[stick[st][i]]=1;
                
          } 
          sq[0]=0; 
          for (int i=1;i<=NumOfSq;++i)
          {
                    if (lstsq[i]) continue;
                    ++sq[0];
                    sq[sq[0]]=i;
                    sqnum[i]=sq[0];
          }    
                rline=0;
                for (int i=1;i<=2*n*(n+1);++i)
                {
                    if (lststick[i]) continue;
                    ++rline;
                    for (int j=1;j<=stick[i][0];++j)
                    {
                        if (lstsq[stick[i][j]]) continue;
                        mat[rline][sqnum[stick[i][j]]]=1;
                    }
                }
          
          initial(rline,sq[0]);
          dfs(0);
          printf("%d\n",res);
    }
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值