dancing link X

今天上午看了看dlx算法,感觉非常巧妙。这里就用数独来举例子好了。

dancing link算法可以用来解决精确覆盖和重复覆盖问题。我暂时只会精确覆盖问题。我们用一个01矩阵来记录我们需要的东西。怎么说呢,就用数独来说吧。我们需要每一行每一列每一宫都只有一个1~9,所以说对于9*9=81个位置,我们得到了4个条件:

1,当前位置只能放一个数。

2,当前位置那一行只能放一种这个数。

3,当前位置那一列只能放一种这个数。

4,当前位置那一宫只能放这一个数。

所以我们关于这三个条件都有9*9种状态,然后81个位置每个位置可以放1~9,所以我们就得到了一个729*324的01矩阵。剩下的就是套板就行了。

dancing之所以快,是因为它的矩阵大小随着递归层数的增加,越来越小。并且它只记录了1的位置,大大缩短了时间。

接下来是数独的板,数独游戏弱爆了。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <iostream>
  4 using namespace std;
  5 #define rp(x,y) (x)*9+y+81
  6 #define cp(x,y) (x)*9+y+162
  7 #define pp(x,y) (x)*9+y+243
  8 const int N = 60003;
  9 const int INF = 0x7fffffff;
 10 int u[N],d[N],L[N],R[N];
 11 int X[N],C[N],s[1003],h[1003],tot,id,ans[103];
 12 bool mark[1003];
 13 struct data {
 14     int pos,val;
 15 }a[1003],q[103];
 16 inline void del(int c) {
 17     L[R[c]] = L[c] ; R[L[c]] = R[c];
 18     for(int i = d[c] ; i != c ; i = d[i])
 19         for(int j = R[i] ; j != i ; j = R[j])
 20             d[u[j]] = d[j] , u[d[j]] = u[j] , s[C[j]]--;
 21 }
 22 inline void add(int c) {    
 23     L[R[c]] = R[L[c]] = c;
 24     for(int i = u[c] ; i != c ; i = u[i])
 25         for(int j = L[i] ; j != i ; j = L[j])
 26             d[u[j]] = u[d[j]] = j , s[C[j]]++;
 27 }
 28 inline void link(int r,int c) {
 29     s[c]++ ; C[++tot] = c ; X[tot] = r;
 30     u[tot] = c ; d[tot] = d[c];
 31     u[d[tot]] = tot ; d[u[tot]] = tot;
 32     if(h[r]==-1) {
 33         h[r] = L[tot] = R[tot] = tot;
 34     } else {
 35         L[tot] = h[r] ; R[tot] = R[h[r]];
 36         L[R[tot]] = tot ; R[L[tot]] = tot;
 37     }
 38 }
 39 inline bool dance(int k) {
 40     if(R[0]==0) {
 41         for(int i = 1 ; i <= 81 ; ++i) ans[q[i].pos] = q[i].val;
 42         for(int i = 1 ; i <= 81 ; ++i) printf("%d",ans[i]);
 43         printf("\n");
 44         return 1;
 45     }
 46     int temp = INF , c = R[0];
 47     for(int i = R[0] ; i ; i = R[i])
 48         if(s[i] < temp) temp = s[i] , c = i;
 49     del(c);
 50     for(int i = d[c] ; i != c ; i = d[i]) {
 51         q[k+1] = a[X[i]];
 52         for(int j = R[i] ; j != i ; j = R[j]) del(C[j]);
 53         if(dance(k+1)) return 1;
 54         for(int j = L[i] ; j != i ; j = L[j]) add(C[j]);
 55     }
 56     add(c);
 57     return 0;
 58 }
 59 char ch[203];
 60 int main() {
 61     while(scanf("%s",ch+1)) {
 62         if(ch[1]=='e') return 0;
 63         id = tot = 0;
 64         memset(h,-1,sizeof(h));
 65         memset(mark,0,sizeof(mark));
 66         for(int i = 0 ; i <= 4*81 ; ++i) {
 67             R[i] = i + 1 ; L[i+1] = i;
 68             u[i] = d[i] = i;
 69             s[i] = 0;
 70         }
 71         L[0] = 4*81 ; R[4*81] = 0 ; tot = 4*81;
 72         for(int i = 0 ; i < 9 ; ++i) 
 73             for(int j = 0 ; j < 9 ; ++j)
 74                 if(ch[i*9+j+1]!='.') {
 75                     int t = ch[i*9+j+1]-'0' , p = i/3*3+j/3;
 76                     mark[rp(i,t)] = mark[cp(j,t)] = mark[pp(p,t)] = 1;
 77                 }
 78         for(int i = 0 ; i < 9 ; ++i)
 79             for(int j = 0 ; j < 9 ; ++j) {
 80                 int t = ch[i*9+j+1]!='.'?ch[i*9+j+1]-'0':0;
 81                 int p = i/3*3+j/3;
 82                 if(t) {
 83                     id++ ; a[id].pos = i*9+j+1 ; a[id].val = t;
 84                     link(id,i*9+j+1);
 85                     link(id,rp(i,t));
 86                     link(id,cp(j,t));
 87                     link(id,pp(p,t));
 88                 } else {
 89                     for(int k = 1 ; k <= 9 ; ++k) {
 90                         if(!mark[rp(i,k)]&&!mark[cp(j,k)]&&!mark[pp(p,k)]) {
 91                             id++ ; a[id].pos = i*9+j+1 ; a[id].val = k;
 92                             link(id,i*9+j+1);
 93                             link(id,rp(i,k));
 94                             link(id,cp(j,k));
 95                             link(id,pp(p,k));
 96                         }
 97                     }
 98                 }
 99             }
100         dance(0);
101     }
102 }
View Code

 

posted @ 2016-01-19 14:48  443singer  阅读(664)  评论(0编辑  收藏  举报