POJ-3074 Dancing Links精确覆盖

题目
行(所有情况)81个格子 * 9个数字=9^3
列(限制条件)
1.每个格子放一个数-81
2.行限制-9行 * 9个数字
3.列限制-9列 * 9个数字
4.小宫格限制-9个小宫格 * 9个数字
把限制条件插入,dancing…
剪枝:先选择数字多的列

#include<stdio.h>
#include<string.h>
using namespace std;
const int N=9;
const int NR=N*N*N+7;
const int NC=N*N*4+7;
const int M=NR*4+NC+7;
char g[NR];
struct Node{
	int u,d,l,r;
	int row,col;
	Node(){}
	Node(int u,int d,int l,int r):u(u),d(d),l(l),r(r){}
	void sign(int _r,int _c){row=_r,col=_c;}
};
struct DLX{
	int n,m,sz;
	Node node[M];
	int head[NR],sc[NC];
	int ans[NR];
	void init(int _n,int _m){
		n=_n,sz=m=_m;
		for(int i=0;i<=m;++i)node[i]=Node(i,i,i-1,i+1),sc[i]=0;
		node[m].r=0,node[0].l=m;
		for(int i=0;i<=n;++i)head[i]=-1;
	}
	void link(int r,int c){
		++sz;
		node[sz].sign(r,c);
		++sc[c];
		node[sz].d=node[c].d;
		node[node[c].d].u=sz;
		node[sz].u=c;
		node[c].d=sz;
		if(head[r]==-1)head[r]=node[sz].l=node[sz].r=sz;
		else{
			node[sz].r=node[head[r]].r;
			node[node[head[r]].r].l=sz;
			node[sz].l=head[r];
			node[head[r]].r=sz;
		}
	}
	void remove(int c){
		node[node[c].r].l=node[c].l;
		node[node[c].l].r=node[c].r;
		for(int i=node[c].d;i^c;i=node[i].d)
			for(int j=node[i].r;j^i;j=node[j].r){
				node[node[j].d].u=node[j].u;
				node[node[j].u].d=node[j].d;
				--sc[node[j].col];
			}
	}
	void resume(int c){
		for(int i=node[c].u;i^c;i=node[i].u)
			for(int j=node[i].l;j^i;j=node[j].l){
				node[node[j].d].u=node[node[j].u].d=j;
				++sc[node[j].col];
			}
		node[node[c].r].l=node[node[c].l].r=c;
	}
	bool dance(int d){
		int c=node[0].r;
		if(!c){
			for(int i=0;i<d;++i)g[(ans[i]-1)/9]=(ans[i]-1)%9+'1';
			for(int i=0;i<N*N;++i)putchar(g[i]);
			puts("");
			return true;
		}
		for(int i=c;i^0;i=node[i].r)if(sc[i]<sc[c])c=i;
		remove(c);
		for(int i=node[c].d;i^c;i=node[i].d){
			ans[d]=node[i].row;
			for(int j=node[i].r;j^i;j=node[j].r)remove(node[j].col);
			if(dance(d+1))return true;
			for(int j=node[i].l;j^i;j=node[j].l)resume(node[j].col);
		}
		resume(c);
		return false;
	}
}sd;
int main(){
	while(gets(g)!=NULL){
		if(g[0]=='e')break;
		sd.init(N*N*N,N*N*4);
		for(int i=0;i<N;++i)for(int j=0;j<N;++j)
		for(int k=1;k<=N;++k)if(g[i*N+j]=='.'||g[i*N+j]=='0'+k){
			int r=(i*N+j)*N+k;
			sd.link(r,i*N+j+1);
			sd.link(r,N*N+i*N+k);
			sd.link(r,N*N*2+j*N+k);
			sd.link(r,N*N*3+((i/3)*3+j/3)*N+k);
		}
		sd.dance(0);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值