dancing link 学习资源导航+心得

dancing link简直是求解数独的神器,NOIP2009最后一题靶形数独,DFS 各种改变搜索顺序 都没法过,最后还是用了卡时过得。用dancing link写,秒杀所有数据,总时间才400ms不到。。(虽然还不是很清楚为什么会快)。

 

一开始还是先看这个blog,图文都非常清晰

http://www.cnblogs.com/grenet/p/3145800.html

上文解释了dancing link的原理,可以用来解决精度覆盖问题,但是求解数独问题还需要一步转化。

见博文:

http://www.cnblogs.com/grenet/p/3163550.html

大致思想是:

1、先遍历数独的格子,把那些有数字的格子转换为行,插入到矩阵中。在插入的同时,把包含1的列的列首元素的Count分量设置为-1(起到后面判别的作用)。

由于这些行一定能被选中,是答案的一部分,那么把这些行的行号置入到答案列表中,并把这些列的列首元素从水平双向链中移除(手动移除比调用RemoveCol方法快)

2、在遍历没有数字的格子,转换为若干行(1个格子9行)插入到矩阵中。在插入到矩阵的时候,判断包含1的列的列首元素的Count分量。如果是-1,说明新插入的行和第1步中的某些行相冲,是个无效行,没有必要插入到矩阵中;如果不是-1,说明是个有效行,插入到矩阵中。

这样把就数独转化成一个729*324的精度覆盖问题;

 

 

看了这个大致有些明白,但要是自己写还是无从下手,先看一个模板(注释比较清晰易懂):

http://blog.csdn.net/weiguang_123/article/details/7935003

看完后可以尝试着做一做裸的精度覆盖问题poj3740,然后再去做靶形数独。

 

另外第一篇文章中有个地方:

在函数中有个很聪明的设计,在标示列首元素时,顺序是从I元素的右侧元素开始;而在回标列首元素时,顺序是从I元素的左侧元素开始,正好顺序和标示列首元素的顺序相反。

 这里非常关键,本来以为无关紧要,把poj3740的代码 顺序改成一样,还是能AC,不过时间慢了一半, 还以为这是个优化时间的地方。但是把靶形数独的代码改成这样,就WA了一半的点,手工模拟下可以发现这个顺序问题不是可有可无的,而是必须的。

 

贴上我靶形数独的AC代码:

  1 #include<cstdio>

  2 #include<iostream>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<cmath>

  6 #include<iomanip> 

  7 using namespace std;

  8 

  9 const int n=729,m=324;

 10 bool mx[2000][2000];

 11 int map[10][10],cnt[2000],head,cur,ans;

 12 int sqr[10][10]={{0,0,0,0,0,0,0,0,0,0},

 13                {0,1,1,1,4,4,4,7,7,7},

 14                {0,1,1,1,4,4,4,7,7,7},

 15                {0,1,1,1,4,4,4,7,7,7},

 16                {0,2,2,2,5,5,5,8,8,8},

 17                {0,2,2,2,5,5,5,8,8,8},

 18                {0,2,2,2,5,5,5,8,8,8},

 19                {0,3,3,3,6,6,6,9,9,9},

 20                {0,3,3,3,6,6,6,9,9,9},

 21                {0,3,3,3,6,6,6,9,9,9}};

 22 

 23 int w[10][10]={{0,0,0,0,0,0,0,0,0,0},

 24                {0,6,6,6,6,6,6,6,6,6},

 25                {0,6,7,7,7,7,7,7,7,6},

 26                {0,6,7,8,8,8,8,8,7,6},

 27                {0,6,7,8,9,9,9,8,7,6},

 28                {0,6,7,8,9,10,9,8,7,6},

 29                {0,6,7,8,9,9,9,8,7,6},

 30                {0,6,7,8,8,8,8,8,7,6},

 31                {0,6,7,7,7,7,7,7,7,6},

 32                {0,6,6,6,6,6,6,6,6,6}};

 33                

 34 struct point

 35 {

 36     int row,lc,rc,up,down,col;

 37 }node[2000*2000];

 38 

 39 inline int id(int x,int y)

 40 {

 41     return (x-1)*9+y;

 42 }

 43 

 44 void init(int c)

 45 {

 46     for (int i=0;i<=c;i++)

 47     {

 48         node[i].lc=i-1;

 49         node[i].rc=i+1;

 50         node[i].up=node[i].down=node[i].col=i;

 51     }

 52     node[0].lc=c;

 53     node[c].rc=0;

 54 }

 55 

 56 void build_link()

 57 {

 58     cur=m;

 59     for (int i=1;i<=n;i++)

 60     {

 61         int start,pre;

 62         start=pre=cur+1;

 63         for (int j=1;j<=m;j++)

 64             if (mx[i][j])

 65             {

 66                 cur++;

 67                 cnt[j]++;

 68                 node[cur].row=i;

 69                 

 70                 node[cur].lc=pre;

 71                 node[cur].rc=start;

 72                 node[pre].rc=cur;

 73                 node[start].lc=cur;

 74                 

 75                 node[cur].col=j;

 76                 node[cur].up=node[j].up;

 77                 node[cur].down=j;

 78                 node[node[j].up].down=cur;

 79                 node[j].up=cur;

 80                 pre=cur;

 81             }

 82     }

 83 }

 84 

 85 inline void cover(int c)

 86 {

 87     for (int i=node[c].up;i!=c;i=node[i].up)

 88         for (int j=node[i].rc;j!=i;j=node[j].rc)

 89         {

 90             node[node[j].up].down=node[j].down;

 91             node[node[j].down].up=node[j].up;

 92             cnt[node[j].col]--;

 93         }

 94     node[node[c].lc].rc=node[c].rc;

 95     node[node[c].rc].lc=node[c].lc;

 96 }

 97 

 98 inline void uncover(int c)

 99 {

100     for (int i=node[c].up;i!=c;i=node[i].up)

101         for (int j=node[i].rc;j!=i;j=node[j].rc)

102         {

103             node[node[j].up].down=j;

104             node[node[j].down].up=j;

105             cnt[node[j].col]++;

106         }

107     node[node[c].lc].rc=c;

108     node[node[c].rc].lc=c;

109 }

110 

111 void read_data()

112 {

113     for (int i=1;i<=9;i++)

114         for (int j=1;j<=9;j++)

115         {

116             scanf("%d",&map[i][j]);

117             int c=id(i,j),t,k;

118             if (map[i][j])

119             {

120                 k=map[i][j];

121                 t=(c-1)*9+k;

122                 mx[t][c]=true;

123                 mx[t][81+9*(i-1)+k]=true;

124                 mx[t][162+9*(j-1)+k]=true;

125                 mx[t][243+(sqr[i][j]-1)*9+k]=true;

126             }

127             else

128             {

129                 for (k=1;k<=9;k++)

130                 {

131                     t=(c-1)*9+k;

132                     mx[t][c]=true;

133                     mx[t][81+9*(i-1)+k]=true;

134                     mx[t][162+9*(j-1)+k]=true;

135                     mx[t][243+(sqr[i][j]-1)*9+k]=true;

136                 }

137             }

138         }

139 }

140 

141 bool dfs(int step,int score)

142 {

143     if (node[head].rc==head)

144     {

145         ans=max(score,ans);

146         return true;

147     }

148     

149     int i,j,c,t=210000,x,y,num,flag=0;

150     for (i=node[head].rc;i!=head;i=node[i].rc)

151         if (cnt[i]<t)

152         {

153             t=cnt[i];

154             c=i;

155         }

156     if (t==0)

157         return false;

158     cover(c);

159     

160     for (i=node[c].down;i!=c;i=node[i].down)

161     {

162         for (j=node[i].lc;j!=i;j=node[j].lc)

163             cover(node[j].col);

164         num=(node[i].row-1)/9+1;

165         x=(num-1)/9+1;

166         y=num-9*(x-1);

167         flag|=dfs(step+1,score+w[x][y]*(node[i].row-(num-1)*9));

168         for (j=node[i].rc;j!=i;j=node[j].rc)

169             uncover(node[j].col);

170     }

171     

172     uncover(c);

173     return flag;

174 }

175 

176 void solve()

177 {

178     init(m);

179     build_link();

180     int flag=1;

181     if (!dfs(1,0))

182         printf("-1\n");

183     else printf("%d\n",ans);

184 }

185 

186 int main()

187 {

188     //freopen("in.in","r",stdin);

189     //freopen("out.out","w",stdout);

190     read_data();

191     solve();

192     return 0;

193 } 
View Code


如果要输出数独填好之后的结果,且数独的解唯一,代码如下:

  1 #include<cstdio>

  2 #include<iostream>

  3 #include<cstring>

  4 #include<algorithm>

  5 #include<cmath>

  6 #include<iomanip> 

  7 using namespace std;

  8 

  9 const int n=729,m=324;

 10 bool mx[2000][2000];

 11 int map[10][10],cnt[2000],head,cur,ans[10][10];

 12 int sqr[10][10]={{0,0,0,0,0,0,0,0,0,0},

 13                {0,1,1,1,4,4,4,7,7,7},

 14                {0,1,1,1,4,4,4,7,7,7},

 15                {0,1,1,1,4,4,4,7,7,7},

 16                {0,2,2,2,5,5,5,8,8,8},

 17                {0,2,2,2,5,5,5,8,8,8},

 18                {0,2,2,2,5,5,5,8,8,8},

 19                {0,3,3,3,6,6,6,9,9,9},

 20                {0,3,3,3,6,6,6,9,9,9},

 21                {0,3,3,3,6,6,6,9,9,9}};

 22                

 23 struct point

 24 {

 25     int row,lc,rc,up,down,col;

 26 }node[2000*2000];

 27 

 28 inline int id(int x,int y)

 29 {

 30     return (x-1)*9+y;

 31 }

 32 

 33 void init(int c)

 34 {

 35     for (int i=0;i<=c;i++)

 36     {

 37         node[i].lc=i-1;

 38         node[i].rc=i+1;

 39         node[i].up=node[i].down=node[i].col=i;

 40     }

 41     node[0].lc=c;

 42     node[c].rc=0;

 43 }

 44 

 45 void build_link()

 46 {

 47     cur=m;

 48     for (int i=1;i<=n;i++)

 49     {

 50         int start,pre;

 51         start=pre=cur+1;

 52         for (int j=1;j<=m;j++)

 53             if (mx[i][j])

 54             {

 55                 cur++;

 56                 cnt[j]++;

 57                 node[cur].row=i;

 58                 

 59                 node[cur].lc=pre;

 60                 node[cur].rc=start;

 61                 node[pre].rc=cur;

 62                 node[start].lc=cur;

 63                 

 64                 node[cur].col=j;

 65                 node[cur].up=node[j].up;

 66                 node[cur].down=j;

 67                 node[node[j].up].down=cur;

 68                 node[j].up=cur;

 69                 pre=cur;

 70             }

 71     }

 72 }

 73 

 74 inline void cover(int c)

 75 {

 76     for (int i=node[c].up;i!=c;i=node[i].up)

 77         for (int j=node[i].rc;j!=i;j=node[j].rc)

 78         {

 79             node[node[j].up].down=node[j].down;

 80             node[node[j].down].up=node[j].up;

 81             cnt[node[j].col]--;

 82         }

 83     node[node[c].lc].rc=node[c].rc;

 84     node[node[c].rc].lc=node[c].lc;

 85 }

 86 

 87 inline void uncover(int c)

 88 {

 89     for (int i=node[c].up;i!=c;i=node[i].up)

 90         for (int j=node[i].rc;j!=i;j=node[j].rc)

 91         {

 92             node[node[j].up].down=j;

 93             node[node[j].down].up=j;

 94             cnt[node[j].col]++;

 95         }

 96     node[node[c].lc].rc=c;

 97     node[node[c].rc].lc=c;

 98 }

 99 

100 void read_data()

101 {

102     for (int i=1;i<=9;i++)

103         for (int j=1;j<=9;j++)

104         {

105             char g;

106             scanf(" %c",&g);

107             map[i][j]=(int)g-'0';

108             int c=id(i,j),t,k;

109             if (map[i][j])

110             {

111                 k=map[i][j];

112                 t=(c-1)*9+k;

113                 mx[t][c]=true;

114                 mx[t][81+9*(i-1)+k]=true;

115                 mx[t][162+9*(j-1)+k]=true;

116                 mx[t][243+(sqr[i][j]-1)*9+k]=true;

117             }

118             else

119             {

120                 for (k=1;k<=9;k++)

121                 {

122                     t=(c-1)*9+k;

123                     mx[t][c]=true;

124                     mx[t][81+9*(i-1)+k]=true;

125                     mx[t][162+9*(j-1)+k]=true;

126                     mx[t][243+(sqr[i][j]-1)*9+k]=true;

127                 }

128             }

129         }

130 }

131 

132 void print()

133 {

134     for (int i=1;i<=9;i++)

135     {

136         for (int j=1;j<=9;j++)

137             printf("%d",ans[i][j]);

138         printf("\n");

139     }

140 }

141 

142 bool dfs(int step)

143 {

144     if (node[head].rc==head)

145     {

146         print();

147         return true;

148     }

149     

150     int i,j,c,t=210000,x,y,num,flag=0;

151     for (i=node[head].rc;i!=head;i=node[i].rc)

152         if (cnt[i]<t)

153         {

154             t=cnt[i];

155             c=i;

156         }

157     if (t==0)

158         return false;

159     cover(c);

160     

161     for (i=node[c].down;i!=c;i=node[i].down)

162     {

163         for (j=node[i].lc;j!=i;j=node[j].lc)

164             cover(node[j].col);

165         num=(node[i].row-1)/9+1;

166         x=(num-1)/9+1;

167         y=num-9*(x-1);

168         ans[x][y]=node[i].row-(num-1)*9;

169         if (dfs(step+1))

170             return true;

171         for (j=node[i].rc;j!=i;j=node[j].rc)

172             uncover(node[j].col);

173     }

174     

175     uncover(c);

176     return false;

177 }

178 

179 void solve()

180 {

181     init(m);

182     build_link();

183     if (!dfs(1))

184         printf("-1\n");

185 }

186 

187 int main()

188 {

189     freopen("alone.in","r",stdin);

190     freopen("alone.out","w",stdout);

191     read_data();

192     solve();

193     return 0;

194 } 
View Code

 

你可能感兴趣的:(link)