(转)数独之Dancing Link解法

(转)数独之Dancing Link解法 默认分类 2009-08-24 19:04:14 阅读575 评论0 字号:大中小 订阅 Dancing Link算法(以下简称DLX)是解NPC难题中的精确覆盖(Exact Cover)的高效算法,一个问题,如果能转化成Exact Cover模型,则都能用DLX解。数独的解法也不列外。 对于一个N*N的(N=K*K)数独,我们可以用一个3位的N进制数rck(0<=r,c,k using namespace std; #define RR 729 #define CC 324 #define INF 1000000000 int mem[RR+9]; int ans[RR+9]; char ch[RR+9]; int cnt[CC+9]; struct node { int r,c; node *up; node *down; node *left; node *right; }head,all[RR*CC+99],row[RR],col[CC];int all_t; inline void link(int r,int c) { cnt[c]++; node *t=&all[all_t++]; t->r=r; t->c=c; t->left=&row[r]; t->right=row[r].right; t->left->right=t; t->right->left=t; t->up=&col[c]; t->down=col[c].down; t->up->down=t; t->down->up=t; } inline void remove(int c) { node *t,*tt; col[c].right->left=col[c].left; col[c].left->right=col[c].right; for(t=col[c].down;t!=&col[c];t=t->down) { for(tt=t->right;tt!=t;tt=tt->right) { cnt[tt->c]--; tt->up->down=tt->down; tt->down->up=tt->up; } t->left->right=t->right; t->right->left=t->left; } } inline void resume(int c) { node *t,*tt; for(t=col[c].down;t!=&col[c];t=t->down) { t->right->left=t; t->left->right=t; for(tt=t->left;tt!=t;tt=tt->left) { cnt[tt->c]++; tt->down->up=tt; tt->up->down=tt; } } col[c].left->right=&col[c]; col[c].right->left=&col[c]; } bool solve(int k) { if(head.right==&head) return true; node*t,*tt; int min=INF,tc; for(t=head.right;t!=&head;t=t->right) { if(cnt[t->c] c]; tc=t->c; if(min<=1)break; } } remove(tc); for(t=col[tc].down;t!=&col[tc];t=t->down) { mem[k]=t->r; t->left->right=t; for(tt=t->right;tt!=t;tt=tt->right) { remove(tt->c); } t->left->right=t->right; if(solve(k+1)) return true; t->right->left=t; for(tt=t->left;tt!=t;tt=tt->left) { resume(tt->c); } t->right->left=t->left; } resume(tc); return false; } int main() { double ss=0; while(gets(ch)) { int i,j,k; if(ch[0]=='e')break; all_t=1; memset(cnt,0,sizeof(cnt)); head.left=&head; head.right=&head; head.up=&head; head.down=&head; head.r=RR; head.c=CC; for(i=0;i right=&col[i]; col[i].right->left=&col[i]; } for(i=0;i down=&row[i]; row[i].down->up=&row[i]; } for(i=0;i right=row[i].right; row[i].right->left=row[i].left; } solve(1); for(i=1;i<=81;i++) { int t=mem[i]/9%81; int val=mem[i]%9+1; ans[t]=val; } for(i=0;i<81;i++) printf("%d",ans[i]); printf("/n"); } }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值