小学期算法--精确覆盖和DLX

 参考自acwing材料

一、DLX相关概念

//以上就是DLX的搜索框架

//下面考虑如何进行剪枝 

二、精确覆盖问题 

三、DLX解数独

思路:

//解题代码: 

#include<bits/stdc++.h>
#pragma GCC optimize(2)//O(2)
#define mem(aaa,bbb) memset(aaa,bbb,sizeof aaa)
using namespace std;
const int N=16,NN=256;
const int SIZE=2e5+10;
int ans[N+10][N+10];
char s[N+10][N+10];
struct DancingLinksX{
    stack<int>s;
    int head[SIZE],siz[SIZE];
    // virtual_head   colunm_size
    int U[SIZE],D[SIZE],L[SIZE],R[SIZE];
    // double direriction loop list
    int row[SIZE],col[SIZE];
    // information of a node
    int n,m,count;
    // size of the map,node count
    void build(int r,int c){//build a map of r*c
        n=r,m=count=c;
        for(int i=0;i<=m;i++){
            L[i]=i-1,R[i]=i+1;
            U[i]=D[i]=i;
            siz[i]=0;
        }
        L[0]=c,R[c]=0;
        mem(head,0);
    }
    void is(int r,int c){//insert a node at (r,c)
        count++;
        col[count]=c,row[count]=r,siz[c]++;
        D[count]=D[c],U[D[c]]=count;
        U[count]=c,D[c]=count;//up-down list operation
        if(!head[r])head[r]=L[count]=R[count]=count;//no node on row r
        else{
            R[count]=R[head[r]],L[R[head[r]]]=count;
            L[count]=head[r],R[head[r]]=count;//left-right list operation
        }
    }
    void rm(int c){//remove a colunm
        L[R[c]]=L[c],R[L[c]]=R[c];
        for(int i=D[c];i!=c;i=D[i])for(int j=R[i];j!=i;j=R[j])
            U[D[j]]=U[j],D[U[j]]=D[j],siz[col[j]]--;
    }
    void rc(int c){//reover a colunm
        for(int i=U[c];i!=c;i=U[i])for(int j=L[i];j!=i;j=L[j])
            D[U[j]]=U[D[j]]=j,siz[col[j]]++;
        L[R[c]]=R[L[c]]=c;
    }
    bool dance(){
        if(!R[0]){
            while(!s.empty()){
                int cur=s.top()-1;s.pop();
                int x=cur/N/N+1;
                int y=cur/N%N+1;
                int p=cur%N+1;
                ans[x][y]=p;
            }
            return 1;
        }
        int nxtc=R[0];
        for(int i=R[0];i!=0;i=R[i])
            if(siz[i]<=siz[nxtc])nxtc=i;
        rm(nxtc);
        for(int i=D[nxtc];i!=nxtc;i=D[i]){
            for(int j=R[i];j!=i;j=R[j])rm(col[j]);
            s.push(row[i]);
            if(dance())return 1;
            s.pop();
            for(int j=L[i];j!=i;j=L[j])rc(col[j]);
        }
        rc(nxtc);
        return 0;
    }
}dlx;
void insert(int r,int c,int p){
    int nr=(r-1)*NN+(c-1)*N+p;
    int _x=(r-1)/4+1,_y=(c-1)/4+1;
    int gri=(_x-1)*4+_y;
    int t1=(r-1)*N+p;//write p in row r
    int t2=NN+(c-1)*N+p;//write p in colunm c
    int t3=NN*2+(gri-1)*N+p;//write p in grid gri
    int t4=NN*3+(r-1)*N+c;//write a number in (r,c)
    dlx.is(nr,t1);
    dlx.is(nr,t2);
    dlx.is(nr,t3);
    dlx.is(nr,t4);
}
int main(){
    while(~scanf("%s",s[1]+1)){
        dlx.build(NN*N,NN*4);
        for(int i=2;i<=N;i++)scanf("%s",s[i]+1);
        for(int i=1;i<=N;i++){
            for(int j=1;j<=N;j++){
                int t=(s[i][j]=='-'?0:s[i][j]-'A'+1);
                ans[i][j]=t;
                if(t)insert(i,j,t);
                else for(int p=1;p<=N;p++)
                    insert(i,j,p);
            }
        }
        dlx.dance();
        for(int i=1;i<=N;puts(""),i++)for(int j=1;j<=N;j++)
            putchar(ans[i][j]+'A'-1);
        puts("");
    }
    return  0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值