kuangbin带我飞QAQ DLX之一脸懵逼

  1. hust 1017 DLX精确覆盖 模板题

勉强写了注释,但还是一脸懵逼,感觉插入方式明显有问题但又不知道哪里不对而且好像能得出正确结果真是奇了怪了

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <map>
  6 #include <vector>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <math.h>
 11 
 12 #define SIGMA_SIZE 26
 13 #define lson rt<<1
 14 #define rson rt<<1|1
 15 #pragma warning ( disable : 4996 )
 16 
 17 using namespace std;
 18 typedef long long LL;
 19 inline LL LMax(LL a,LL b)    { return a>b?a:b; }
 20 inline LL LMin(LL a,LL b)    { return a>b?b:a; }
 21 inline int Max(int a,int b) { return a>b?a:b; }
 22 inline int Min(int a,int b) { return a>b?b:a; }
 23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 25 const LL INF = 0x3f3f3f3f3f3f3f3f;
 26 const LL mod  = 1000000007;
 27 const int inf  = 0x3f3f3f3f;
 28 const int maxk = 1e5+5;
 29 const int maxn = 1e4+5;
 30 
 31 
 32 //第一行为虚拟行,是人为加上的,一共有m+1个点(第一个点独立于整个矩阵)
 33 //而后加入的值为1的点标号用size表示
 34 //即第一行一共m+1个点,所以size先从0~m,之后每加入一个为1的点,size++
 35 //大部分数组X都用X[size]来标识标号为size的点的信息
 36 struct DLX {
 37     int n, m, size, fin;
 38     int U[maxn], D[maxn], L[maxn], R[maxn];//上下左右
 39     int head[maxn], S[maxn];                //分别存每一行第一个1的点的标号和每一列1的个数
 40     int row[maxn], col[maxn], ans[maxn];    //row,col表示第size个点在哪一行/列
 41 
 42 
 43     void init( int _n, int _m )
 44     {
 45         n = _n; m = _m;
 46         for ( int i = 0; i <= m; i++ )    //初始化第一行(人为增加的虚拟行)
 47         {
 48             S[i] = 0;
 49             U[i] = D[i] = i;
 50             L[i] = i-1;
 51             R[i] = i+1;
 52         }
 53         R[m] = 0; L[0] = m;        //第一行的最后一个元素指向第一个
 54         size = m;                //从m开始以后都是普通节点
 55         memset( head, -1, sizeof(head) );
 56         head[0] = 0;
 57     }
 58 
 59     void link( int r, int c )
 60     {
 61         size++;                    //得到新的点标号
 62         col[size] = c;            //第size个点在第c列
 63         row[size] = r;            //第size个点在第r行
 64         S[c]++;                    //第c列1的个数+1
 65         
 66         //组成一个环,和下面左右一样的插法
 67         D[size] = D[c];            
 68         U[size] = c;            
 69         U[D[c]] = size;            
 70         D[c] = size;        
 71 
 72         //如果该行没有为1的节点
 73         if ( head[r] < 0 ) head[r] = L[size] = R[size] = size;
 74         else
 75         {
 76             //组成一个环,插在head[r]和head[r]右边那个元素中间
 77             R[size] = R[head[r]];        
 78             L[R[size]] = size;
 79             L[size] = head[r];
 80             R[head[r]] = size;
 81         }
 82     }
 83 
 84     void remove( int c )   //删除列c及其所在行
 85     {
 86         L[R[c]] = L[c]; R[L[c]] = R[c];                //c的左右两个节点互相连接
 87         for ( int i = D[c]; i != c; i = D[i] )        //屏蔽c列
 88             for ( int j = R[i]; j != i; j = R[j] )
 89             {
 90                 U[D[j]] = U[j];
 91                 D[U[j]] = D[j];
 92                 --S[col[j]];        //j所在的列的1的数目数减少
 93             }
 94     }
 95 
 96     void resume( int c )
 97     {
 98         for ( int i = U[c]; i != c; i = U[i] )
 99             for ( int j = L[i]; j != i; j = L[j] )
100             {
101                 U[D[j]] = D[U[j]] = j;
102                 ++S[col[j]];
103             }
104         L[R[c]] = R[L[c]] = c;
105     }
106 
107     bool dance( int d )
108     {
109         if ( R[0] == 0 ) //第0行没有节点
110         {
111             fin = d;
112             return true;
113         }
114 
115         //找出含1数目最小的一列
116         int mark = R[0];
117         for ( int i = R[0]; i != 0; i = R[i] )
118             if ( S[i] < S[mark] )
119                 mark = i;
120 
121         remove(mark);    //移除列mark的1的对应行
122         for ( int i = D[mark]; i != mark; i = D[i] )
123         {
124             ans[d] = row[i];
125             //移除该行的1的对应列
126             for ( int j = R[i]; j != i; j = R[j] )
127                 remove(col[j]);
128 
129             if ( dance(d+1) )
130                 return true;
131 
132             //倒着恢复
133             for ( int j = L[i]; j != i; j = L[j] )
134                 resume(col[j]);
135         }
136         resume(mark);
137         return false;
138     }
139 }dlx;
140 
141 
142 int main()
143 {
144     //freopen("F:\\cpp\\test.txt","r",stdin); 
145 
146     int n, m;
147     while ( ~scanf("%d %d", &n, &m) )
148     {
149         dlx.init(n,m);
150         for ( int i = 1; i <= n; i++ )
151         {
152             int num, j;
153             scanf("%d",&num);
154             while (num--)
155             {
156                 scanf("%d",&j);
157                 dlx.link(i,j);
158             }
159         }
160 
161         if ( dlx.dance(0) )
162         {
163             printf( "%d", dlx.fin );
164             for ( int i = 0; i < dlx.fin; i++ )
165                 printf( " %d", dlx.ans[i] );
166             printf( "\n" );
167             //continue;
168         }
169         else
170             printf("NO\n");
171     }
172     
173     return 0;
174 }
View Code

  2. ZOJ 3209 矩阵映射DLX精确覆盖

  给一个大矩阵和p个小矩阵,问在p个小矩阵中能否取若干个使它们覆盖整个大矩阵,并且小矩阵间两两互不覆盖。

把大矩阵分为1-n*m个小块(就是横竖切割n和m次),则题目的要求就变成了每个小块都要被一个且仅能有一个小矩阵覆盖,然后就是映射了,因为每个小矩阵能覆盖1~n*m这么多编号小块中的某些块,那么我们让每个小矩阵为1行,并设n*m列,则题目就变成p行n*m列的矩阵对其求精确覆盖了

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <map>
  6 #include <vector>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <math.h>
 11 
 12 #define SIGMA_SIZE 26
 13 #define lson rt<<1
 14 #define rson rt<<1|1
 15 #pragma warning ( disable : 4996 )
 16 
 17 using namespace std;
 18 typedef long long LL;
 19 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
 20 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
 21 inline int Max(int a,int b)    { return a>b?a:b; }
 22 inline int Min(int a,int b)       { return a>b?b:a; }
 23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 25 const LL INF = 0x3f3f3f3f3f3f3f3f;
 26 const LL mod  = 1000000007;
 27 const int inf  = 0x3f3f3f3f;
 28 const int maxk = 1e5+5;
 29 const int maxn = 1e5;
 30 
 31 struct DLX {
 32     int n, m, size, fin;
 33     int U[maxn], D[maxn], L[maxn], R[maxn]; //上下左右
 34     int head[maxn], S[maxn];                //分别存每一行第一个1的点的标号和每一列1的个数
 35     int row[maxn], col[maxn], ans[maxn];    //row,col表示第size个点在哪一行/列
 36 
 37 
 38     void init( int _n, int _m )
 39     {
 40         n = _n; m = _m;
 41         for ( int i = 0; i <= m; i++ )    //初始化第一行(人为增加的虚拟行)
 42         {
 43             S[i] = 0;
 44             U[i] = D[i] = i;
 45             L[i] = i-1;
 46             R[i] = i+1;
 47         }
 48         R[m] = 0; L[0] = m;        //第一行的最后一个元素指向第一个
 49         fin = -1; size = m;                //从m开始以后都是普通节点
 50         memset( head, -1, sizeof(head) );
 51     }
 52 
 53     void link( int r, int c )
 54     {
 55         size++;                    //得到新的点标号
 56         col[size] = c;            //第size个点在第c列
 57         row[size] = r;            //第size个点在第r行
 58         S[c]++;                    //第c列1的个数+1
 59         
 60         //组成一个环,和下面左右一样的插法
 61         D[size] = D[c];            
 62         U[size] = c;            
 63         U[D[c]] = size;            
 64         D[c] = size;        
 65 
 66         //如果该行没有为1的节点
 67         if ( head[r] < 0 ) head[r] = L[size] = R[size] = size;
 68         else
 69         {
 70             //组成一个环,插在head[r]和head[r]右边那个元素中间
 71             R[size] = R[head[r]];        
 72             L[R[size]] = size;
 73             L[size] = head[r];
 74             R[head[r]] = size;
 75         }
 76     }
 77 
 78     void remove( int c )   //删除列c及其所在行
 79     {
 80         L[R[c]] = L[c]; R[L[c]] = R[c];                //c的左右两个节点互相连接
 81         for ( int i = D[c]; i != c; i = D[i] )        //屏蔽c列
 82             for ( int j = R[i]; j != i; j = R[j] )
 83             {
 84                 U[D[j]] = U[j];
 85                 D[U[j]] = D[j];
 86                 --S[col[j]];        //j所在的列的1的数目数减少
 87             }
 88     }
 89 
 90     void resume( int c )
 91     {
 92         for ( int i = U[c]; i != c; i = U[i] )
 93             for ( int j = L[i]; j != i; j = L[j] )
 94             {
 95                 U[D[j]] = D[U[j]] = j;
 96                 ++S[col[j]];
 97             }
 98         L[R[c]] = R[L[c]] = c;
 99     }
100 
101     void dance( int d )
102     {
103         if ( fin != -1 && fin <= d )
104             return;
105         if ( R[0] == 0 ) //第0行没有节点
106         {
107             fin = d;
108             return;
109         }
110 
111         //找出含1数目最小的一列
112         int mark = R[0];
113         for ( int i = R[0]; i != 0; i = R[i] )
114             if ( S[i] < S[mark] )
115                 mark = i;
116 
117         remove(mark);    //移除列mark的1的对应行
118         for ( int i = D[mark]; i != mark; i = D[i] )
119         {
120             ans[d] = row[i];
121             //移除该行的1的对应列
122             for ( int j = R[i]; j != i; j = R[j] )
123                 remove(col[j]);
124 
125             dance(d+1);
126 
127             //倒着恢复
128             for ( int j = L[i]; j != i; j = L[j] )
129                 resume(col[j]);
130         }
131         resume(mark);
132 
133         return;
134     }
135 }dlx;
136 
137 
138 int pos[32][32];
139 
140 int main()
141 {
142     freopen("F:\\cpp\\test.txt","r",stdin); 
143 
144     int n, m, p;
145     int x1, x2, y1, y2;
146     int T; cin >> T;
147     while (T--)
148     {
149         scanf("%d %d %d", &n, &m, &p);
150         dlx.init(p, n*m);
151 
152         int id = 1;
153         for ( int i = 1; i <= n; i++ )
154             for ( int j = 1; j <= m; j++ )
155                 pos[i][j] = id++;
156 
157         for ( int r = 1; r <= p; r++ )
158         {
159             scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
160             //注意对应的规则
161             for ( int i = x1+1; i <= x2; i++ )
162                 for ( int j = y1+1; j <= y2; j++ )
163                     dlx.link( r, pos[i][j] );
164         }
165 
166         dlx.dance(0);
167         printf("%d\n", dlx.fin);
168     }
169 
170     return 0;
171 }
View Code

 懒得修改了...直接贴另一种返回

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <map>
  6 #include <vector>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <math.h>
 11 
 12 #define SIGMA_SIZE 26
 13 #define lson rt<<1
 14 #define rson rt<<1|1
 15 #pragma warning ( disable : 4996 )
 16 
 17 using namespace std;
 18 typedef long long LL;
 19 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
 20 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
 21 inline int Max(int a,int b)    { return a>b?a:b; }
 22 inline int Min(int a,int b)       { return a>b?b:a; }
 23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 25 const LL INF = 0x3f3f3f3f3f3f3f3f;
 26 const LL mod  = 1000000007;
 27 const int inf  = 0x3f3f3f3f;
 28 const int maxk = 1e5+5;
 29 const int maxn = 1e5;
 30 
 31 struct DLX {
 32     int n, m, size, fin;
 33     int U[maxn], D[maxn], L[maxn], R[maxn]; //上下左右
 34     int head[maxn], S[maxn];                //分别存每一行第一个1的点的标号和每一列1的个数
 35     int row[maxn], col[maxn], ans[maxn];    //row,col表示第size个点在哪一行/列
 36 
 37 
 38     void init( int _n, int _m )
 39     {
 40         n = _n; m = _m;
 41         for ( int i = 0; i <= m; i++ )    //初始化第一行(人为增加的虚拟行)
 42         {
 43             S[i] = 0;
 44             U[i] = D[i] = i;
 45             L[i] = i-1;
 46             R[i] = i+1;
 47         }
 48         R[m] = 0; L[0] = m;        //第一行的最后一个元素指向第一个
 49         fin = -1; size = m;                //从m开始以后都是普通节点
 50         memset( head, -1, sizeof(head) );
 51     }
 52 
 53     void link( int r, int c )
 54     {
 55         size++;                    //得到新的点标号
 56         col[size] = c;            //第size个点在第c列
 57         row[size] = r;            //第size个点在第r行
 58         S[c]++;                    //第c列1的个数+1
 59         
 60         //组成一个环,和下面左右一样的插法
 61         D[size] = D[c];            
 62         U[size] = c;            
 63         U[D[c]] = size;            
 64         D[c] = size;        
 65 
 66         //如果该行没有为1的节点
 67         if ( head[r] < 0 ) head[r] = L[size] = R[size] = size;
 68         else
 69         {
 70             //组成一个环,插在head[r]和head[r]右边那个元素中间
 71             R[size] = R[head[r]];        
 72             L[R[size]] = size;
 73             L[size] = head[r];
 74             R[head[r]] = size;
 75         }
 76     }
 77 
 78     void remove( int c )   //删除列c及其所在行
 79     {
 80         L[R[c]] = L[c]; R[L[c]] = R[c];                //c的左右两个节点互相连接
 81         for ( int i = D[c]; i != c; i = D[i] )        //屏蔽c列
 82             for ( int j = R[i]; j != i; j = R[j] )
 83             {
 84                 U[D[j]] = U[j];
 85                 D[U[j]] = D[j];
 86                 --S[col[j]];        //j所在的列的1的数目数减少
 87             }
 88     }
 89 
 90     void resume( int c )
 91     {
 92         for ( int i = U[c]; i != c; i = U[i] )
 93             for ( int j = L[i]; j != i; j = L[j] )
 94             {
 95                 U[D[j]] = D[U[j]] = j;
 96                 ++S[col[j]];
 97             }
 98         L[R[c]] = R[L[c]] = c;
 99     }
100 
101     bool dance( int d )
102     {
103         if ( fin != -1 && fin <= d )
104             return false;
105         if ( R[0] == 0 ) //第0行没有节点
106         {
107             fin = d;
108             return true;
109         }
110 
111         //找出含1数目最小的一列
112         int mark = R[0];
113         for ( int i = R[0]; i != 0; i = R[i] )
114             if ( S[i] < S[mark] )
115                 mark = i;
116 
117         remove(mark);    //移除列mark的1的对应行
118         for ( int i = D[mark]; i != mark; i = D[i] )
119         {
120             ans[d] = row[i];
121             //移除该行的1的对应列
122             for ( int j = R[i]; j != i; j = R[j] )
123                 remove(col[j]);
124 
125             dance(d+1);
126 
127             //倒着恢复
128             for ( int j = L[i]; j != i; j = L[j] )
129                 resume(col[j]);
130         }
131         resume(mark);
132 
133         return false;
134     }
135 }dlx;
136 
137 
138 int pos[32][32];
139 
140 int main()
141 {
142     freopen("F:\\cpp\\test.txt","r",stdin); 
143 
144     int n, m, p;
145     int x1, x2, y1, y2;
146     int T; cin >> T;
147     while (T--)
148     {
149         scanf("%d %d %d", &n, &m, &p);
150         dlx.init(p, n*m);
151 
152         int id = 1;
153         for ( int i = 1; i <= n; i++ )
154             for ( int j = 1; j <= m; j++ )
155                 pos[i][j] = id++;
156 
157         for ( int r = 1; r <= p; r++ )
158         {
159             scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
160             //注意对应的规则
161             for ( int i = x1+1; i <= x2; i++ )
162                 for ( int j = y1+1; j <= y2; j++ )
163                     dlx.link( r, pos[i][j] );
164         }
165 
166         dlx.dance(0);
167         printf("%d\n", dlx.fin);
168     }
169 
170     return 0;
171 }
View Code

   3.HDU 2295 圆形重复覆盖+二分

  一脸懵逼逼逼....如果说之前那个模板还勉强看的懂...这个就完全懵逼了(还非常容易写错)。题目比较简单就不说了

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <map>
  6 #include <vector>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <math.h>
 11 
 12 #define SIGMA_SIZE 26
 13 #define lson rt<<1
 14 #define rson rt<<1|1
 15 #pragma warning ( disable : 4996 )
 16 
 17 using namespace std;
 18 typedef long long LL;
 19 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
 20 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
 21 inline int Max(int a,int b)    { return a>b?a:b; }
 22 inline int Min(int a,int b)       { return a>b?b:a; }
 23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 25 const LL INF = 0x3f3f3f3f3f3f3f3f;
 26 const LL mod  = 1000000007;
 27 const double eps = 1e-8;
 28 const int inf  = 0x3f3f3f3f;
 29 const int maxk = 1e4;
 30 const int maxn = 105;
 31 
 32 struct DLX {
 33     int n, m, size, fin;
 34     int U[maxk], D[maxk], L[maxk], R[maxk];
 35     int C[maxk];
 36 
 37     int head[maxk];
 38     int S[maxk];
 39     bool vis[maxk];
 40 
 41     void init( int _n, int _m )
 42     {
 43         n = _n; m = _m;
 44         for ( int i = 0; i <= m; i++ )
 45         {
 46             U[i] = D[i] = i;
 47             L[i] = i-1;
 48             R[i] = i+1;
 49             S[i] = 0;
 50         }
 51         L[0] = m; R[m] = 0;
 52         size = m;
 53         memset( head, -1, sizeof(head) );
 54     }
 55     
 56     void link( int r, int c )
 57     {
 58         size++;
 59         C[size] = c;
 60         S[c]++;
 61         
 62         D[size] = D[c];
 63         U[size] = c;
 64         U[D[c]] = size;
 65         D[c] = size;
 66 
 67         if ( head[r] < 0 )
 68             head[r] = L[size] = R[size] = size;
 69         else
 70         {
 71             R[size] = R[head[r]];
 72             L[R[size]] = size;
 73             L[size] = head[r];
 74             R[head[r]] = size;
 75         }
 76     }
 77 
 78     void remove( int id )
 79     {
 80         for ( int i = D[id]; i != id; i = D[i] )
 81         {
 82             L[R[i]] = L[i];
 83             R[L[i]] = R[i];
 84         }
 85     }
 86 
 87     void resume( int id )
 88     {
 89         for ( int i = D[id]; i != id; i = D[i] )
 90             L[R[i]] = R[L[i]] = i;
 91     }
 92 
 93     int h()
 94     {
 95         int sum = 0;
 96         memset( vis, 0, sizeof(vis) );
 97         for ( int i = R[0]; i != 0; i = R[i] )
 98             if (!vis[i])
 99             {
100                 sum++;
101                 for ( int j = D[i]; j != i; j = D[j] )
102                     for ( int k = R[j]; k != j; k = R[k] )
103                         vis[C[k]] = 1;
104             }
105         return sum;
106     }
107 
108     void dance( int k )
109     {
110         int mark, mmin = inf;
111         if ( k + h() >= fin )
112             return;
113         if ( R[0] == 0 )
114         {
115             if ( k < fin )
116                 fin = k;
117             return;
118         }
119 
120         for ( int i = R[0]; i != 0; i = R[i] )
121             if ( mmin > S[i] )
122             {
123                 mmin = S[i];
124                 mark = i;
125             }
126 
127         for ( int i = D[mark]; i != mark; i = D[i] )
128         {
129             remove(i);
130             for ( int j = R[i]; j != i; j = R[j] ) remove(j);
131             dance(k+1);
132             for ( int j = R[i]; j != i; j = R[j] ) resume(j);
133             resume(i);
134         }
135     }
136 }dlx;
137 
138 double mmap[maxn][2];
139 double cir[maxn][2];
140 
141 void init( int n, int m )
142 {
143     for ( int i = 1; i <= n; i++ )
144         scanf("%lf %lf", &mmap[i][0], &mmap[i][1]);
145     for ( int i = 1; i <= m; i++ )
146         scanf("%lf %lf", &cir[i][0], &cir[i][1]);
147 }
148 
149 double getdis( int i, int j )
150 {
151     double a = mmap[i][0] - cir[j][0];
152     double b = mmap[i][1] - cir[j][1];
153     a *= a; b *= b;
154     return sqrt(a+b);
155 }
156 
157 bool judge( int n, int m, int k, double r )
158 {
159     dlx.init(m, n); dlx.fin = inf;
160 
161     for ( int i = 1; i <= n; i++ )
162         for ( int j = 1; j <= m; j++ )
163         {
164             if ( r >= getdis(i,j) )
165                 dlx.link(j,i);
166         }
167     dlx.dance(0);
168     if ( dlx.fin <= k ) return 1;
169     else return 0;
170 }
171 
172 int main()
173 {
174 #ifdef local
175     freopen("F:\\cpp\\test.txt","r",stdin); 
176 #endif
177 
178     int n, m, k;
179     int T; cin >> T;
180     while (T--)
181     {
182         scanf("%d %d %d", &n, &m, &k);
183         init(n,m);
184 
185         double mid, lhs = 0.0, rhs = 1000.0;
186         while ( rhs - lhs > eps )
187         {
188             mid = (lhs+rhs) / 2;
189             if ( judge(n,m,k,mid) )
190                 rhs = mid;
191             else
192                 lhs = mid;
193         }
194         printf("%.6lf\n", (lhs+rhs)/2);
195     }
196     return 0;
197 }
View Code

   4.FZU 1686 矩形重复覆盖

  原来DLX主要是考察建模啊,模板实在不想每次都打一遍了...直接ctrl+c

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <map>
  6 #include <vector>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <math.h>
 11 
 12 #define SIGMA_SIZE 26
 13 #define lson rt<<1
 14 #define rson rt<<1|1
 15 #pragma warning ( disable : 4996 )
 16 
 17 using namespace std;
 18 typedef long long LL;
 19 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
 20 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
 21 inline int Max(int a,int b)    { return a>b?a:b; }
 22 inline int Min(int a,int b)       { return a>b?b:a; }
 23 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 24 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 25 const LL INF = 0x3f3f3f3f3f3f3f3f;
 26 const LL mod  = 1000000007;
 27 const double eps = 1e-8;
 28 const int inf  = 0x3f3f3f3f;
 29 const int maxk = 1000;
 30 const int maxn = 105;
 31 
 32 struct DLX {
 33     int n, m, size, fin;
 34     int U[maxk], D[maxk], L[maxk], R[maxk];
 35     int C[maxk];
 36 
 37     int head[maxk];
 38     int S[maxk];
 39     bool vis[maxk];
 40 
 41     void init( int _n, int _m )
 42     {
 43         n = _n; m = _m;
 44         for ( int i = 0; i <= m; i++ )
 45         {
 46             U[i] = D[i] = i;
 47             L[i] = i-1;
 48             R[i] = i+1;
 49             S[i] = 0;
 50         }
 51         L[0] = m; R[m] = 0;
 52         fin = inf; size = m;
 53         memset( head, -1, sizeof(head) );
 54     }
 55 
 56     void link( int r, int c )
 57     {
 58         size++;
 59         C[size] = c;
 60         S[c]++;
 61 
 62         D[size] = D[c];
 63         U[size] = c;
 64         U[D[c]] = size;
 65         D[c] = size;
 66 
 67         if ( head[r] < 0 )
 68             head[r] = L[size] = R[size] = size;
 69         else
 70         {
 71             R[size] = R[head[r]];
 72             L[R[size]] = size;
 73             L[size] = head[r];
 74             R[head[r]] = size;
 75         }
 76     }
 77 
 78     void remove( int id )
 79     {
 80         for ( int i = D[id]; i != id; i = D[i] )
 81         {
 82             L[R[i]] = L[i];
 83             R[L[i]] = R[i];
 84         }
 85     }
 86 
 87     void resume( int id )
 88     {
 89         for ( int i = D[id]; i != id; i = D[i] )
 90             L[R[i]] = R[L[i]] = i;
 91     }
 92 
 93     int h()
 94     {
 95         int sum = 0;
 96         memset( vis, 0, sizeof(vis) );
 97         for ( int i = R[0]; i != 0; i = R[i] )
 98             if (!vis[i])
 99             {
100                 sum++;
101                 for ( int j = D[i]; j != i; j = D[j] )
102                     for ( int k = R[j]; k != j; k = R[k] )
103                         vis[C[k]] = 1;
104             }
105         return sum;
106     }
107 
108     void dance( int k )
109     {
110         int mark, mmin = inf;
111         if ( k + h() >= fin )
112             return;
113         if ( R[0] == 0 )
114         {
115             if ( k < fin )
116                 fin = k;
117             return;
118         }
119 
120         for ( int i = R[0]; i != 0; i = R[i] )
121             if ( mmin > S[i] )
122             {
123                 mmin = S[i];
124                 mark = i;
125             }
126 
127         for ( int i = D[mark]; i != mark; i = D[i] )
128         {
129             remove(i);
130             for ( int j = R[i]; j != i; j = R[j] ) remove(j);
131             dance(k+1);
132             for ( int j = R[i]; j != i; j = R[j] ) resume(j);
133             resume(i);
134         }
135     }
136 }dlx;
137 
138 int mmap[20][20], g[20][20];
139 
140 void init()
141 {
142     memset( mmap, 0, sizeof(mmap) );
143     memset( g, 0, sizeof(g) );
144 }
145 
146 int main()
147 {
148 #ifdef local
149     freopen("F:\\cpp\\test.txt","r",stdin); 
150 #endif
151 
152     int R, C, r, c;
153     while ( ~scanf("%d %d", &R, &C) )
154     {
155         init();
156         int cnt = 0;
157         for ( int i = 1; i <= R; i++ )
158             for (int j = 1; j <= C; j++)
159             {
160                 scanf("%d", &mmap[i][j]);
161                 if ( mmap[i][j] )
162                     g[i][j] = ++cnt;
163             }
164         scanf("%d %d", &r, &c);
165         dlx.init( (R-r+1)*(C-c+1), cnt ); 
166 
167         cnt = 1;
168         for ( int i = 1; i+r-1 <= R; i++ )
169             for ( int j = 1; j+c-1 <= C; j++ )
170             {
171                 for ( int a = i; a <= i+r-1; a++ )
172                     for ( int b = j; b <= j + c - 1; b++ )
173                         if (g[a][b])
174                             dlx.link(cnt, g[a][b]);
175                 cnt++;
176             }
177         dlx.dance(0);
178         printf("%d\n", dlx.fin);
179     }
180     
181     return 0;
182 }
View Code

   5.POJ 3074

  求解数独....emmmm我得好好理解下才行

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <map>
  6 #include <vector>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <math.h>
 11 #include <time.h>
 12 
 13 #define SIGMA_SIZE 26
 14 #define lson rt<<1
 15 #define rson rt<<1|1
 16 #pragma warning ( disable : 4996 )
 17 
 18 using namespace std;
 19 typedef long long LL;
 20 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
 21 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
 22 inline int Max(int a,int b)    { return a>b?a:b; }
 23 inline int Min(int a,int b)       { return a>b?b:a; }
 24 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 25 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 26 const LL INF = 0x3f3f3f3f3f3f3f3f;
 27 const LL mod  = 1000000007;
 28 const double eps = 1e-8;
 29 const int inf  = 0x3f3f3f3f;
 30 const int maxk = 1e8;
 31 const int maxn = 5000;
 32 
 33 struct node {
 34     int x, y, k;
 35 }e[800];
 36 
 37 struct DLX {
 38     int n, m, size, fin;
 39     int U[maxn], D[maxn], L[maxn], R[maxn];//上下左右
 40     int head[maxn], S[maxn];                //分别存每一行第一个1的点的标号和每一列1的个数
 41     int row[maxn], col[maxn], ans[maxn];    //row,col表示第size个点在哪一行/列
 42 
 43 
 44     void init( int _n, int _m )
 45     {
 46         n = _n; m = _m;
 47         for ( int i = 0; i <= m; i++ )    //初始化第一行(人为增加的虚拟行)
 48         {
 49             S[i] = 0;
 50             U[i] = D[i] = i;
 51             L[i] = i-1;
 52             R[i] = i+1;
 53         }
 54         R[m] = 0; L[0] = m;        //第一行的最后一个元素指向第一个
 55         size = m;                //从m开始以后都是普通节点
 56         memset( head, -1, sizeof(head) );
 57         head[0] = 0;
 58     }
 59 
 60     void link( int r, int c )
 61     {
 62         size++;                    //得到新的点标号
 63         col[size] = c;            //第size个点在第c列
 64         row[size] = r;            //第size个点在第r行
 65         S[c]++;                    //第c列1的个数+1
 66 
 67                                    //组成一个环,和下面左右一样的插法
 68         D[size] = D[c];            
 69         U[size] = c;            
 70         U[D[c]] = size;            
 71         D[c] = size;        
 72 
 73         //如果该行没有为1的节点
 74         if ( head[r] < 0 ) head[r] = L[size] = R[size] = size;
 75         else
 76         {
 77             //组成一个环,插在head[r]和head[r]右边那个元素中间
 78             R[size] = R[head[r]];        
 79             L[R[size]] = size;
 80             L[size] = head[r];
 81             R[head[r]] = size;
 82         }
 83     }
 84 
 85     void remove( int c )   //删除列c及其所在行
 86     {
 87         L[R[c]] = L[c]; R[L[c]] = R[c];                //c的左右两个节点互相连接
 88         for ( int i = D[c]; i != c; i = D[i] )        //屏蔽c列
 89             for ( int j = R[i]; j != i; j = R[j] )
 90             {
 91                 U[D[j]] = U[j];
 92                 D[U[j]] = D[j];
 93                 --S[col[j]];        //j所在的列的1的数目数减少
 94             }
 95     }
 96 
 97     void resume( int c )
 98     {
 99         for ( int i = U[c]; i != c; i = U[i] )
100             for ( int j = L[i]; j != i; j = L[j] )
101             {
102                 U[D[j]] = D[U[j]] = j;
103                 ++S[col[j]];
104             }
105         L[R[c]] = R[L[c]] = c;
106     }
107 
108     bool dance( int d )
109     {
110         if ( R[0] == 0 ) //第0行没有节点
111         {
112             fin = d;
113             return true;
114         }
115 
116         //找出含1数目最小的一列
117         int mark = R[0];
118         for ( int i = R[0]; i != 0; i = R[i] )
119             if ( S[i] < S[mark] )
120                 mark = i;
121 
122         remove(mark);    //移除列mark的1的对应行
123         for ( int i = D[mark]; i != mark; i = D[i] )
124         {
125             ans[d] = row[i];
126             //移除该行的1的对应列
127             for ( int j = R[i]; j != i; j = R[j] )
128                 remove(col[j]);
129 
130             if ( dance(d+1) )
131                 return true;
132 
133             //倒着恢复
134             for ( int j = L[i]; j != i; j = L[j] )
135                 resume(col[j]);
136         }
137         resume(mark);
138         return false;
139     }
140 }dlx;
141 
142 
143 int mmap[10][10];
144 char sudoku[90];
145 
146 void read()
147 {
148     dlx.init(750,324);
149     int row = 0;
150 
151     for ( int i = 1; i <= 9; i++ )
152         for ( int j = 1; j <= 9; j++ )
153         {
154             if ( !mmap[i][j] )
155             {
156                 for ( int k = 1; k <= 9; k++ )
157                 {
158                     ++row;
159                     dlx.link(row, (i-1)*9+j);
160                     dlx.link(row, 81+(i-1)*9+k);
161                     dlx.link(row, 162+(j-1)*9+k);
162                     dlx.link(row,243+(((i-1)/3)*3+(j+2)/3-1)*9+k);
163                     e[row].x = i; e[row].y = j; e[row].k = k;
164                 }
165             }
166             else
167             {
168                 ++row;
169                 int k = mmap[i][j];
170                 dlx.link(row, (i-1)*9+j);
171                 dlx.link(row, 81+(i-1)*9+k);
172                 dlx.link(row, 162+(j-1)*9+k);
173                 dlx.link(row, 243+(((i-1)/3)*3+(j+2)/3-1)*9+k);
174                 e[row].x = i; e[row].y = j; e[row].k = k;
175             }
176         }
177 
178 }
179 
180 void init()
181 {
182     int t = 0;
183 
184     for ( int i = 1; i <= 9; i++ )
185         for ( int j = 1; j <= 9; j++ )
186         {
187             if ( sudoku[++t] != '.' )
188                 mmap[i][j] = sudoku[t] - '0';
189             else
190                 mmap[i][j] = 0;
191         }
192 
193     read();
194 }
195 
196 int main()
197 {
198     //freopen("F:\\cpp\\test.txt", "r", stdin );
199 
200     while ( ~scanf("%s", sudoku+1) )
201     {
202         if (sudoku[1] == 'e') break;
203         init();
204 
205         dlx.dance(0);
206         for ( int i = 0; i < dlx.fin; i++ )
207         {
208             int tmp = dlx.ans[i];
209             sudoku[(e[tmp].x-1)*9 + e[tmp].y-1] = '0'+e[tmp].k;
210         }
211         sudoku[dlx.fin] = '\0';
212         printf("%s\n", sudoku);
213     }
214 
215     return 0;
216 }
View Code

   6. HDU 5046

  和hdu2295基本一样,有个可以优化的方法是将可行的距离排序后二分下标,如果不这样做直接二分,左右区间要到1~4e9才行,而且大概率TLE(交了一发1300ms)

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <map>
  6 #include <vector>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <math.h>
 11 #include <time.h>
 12 
 13 #define SIGMA_SIZE 26
 14 #define lson rt<<1
 15 #define rson rt<<1|1
 16 #pragma warning ( disable : 4996 )
 17 
 18 using namespace std;
 19 typedef long long LL;
 20 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
 21 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
 22 inline int Max(int a,int b)    { return a>b?a:b; }
 23 inline int Min(int a,int b)       { return a>b?b:a; }
 24 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 25 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 26 const LL INF = 0x3f3f3f3f3f3f3f3f;
 27 const LL mod  = 1000000007;
 28 const double eps = 1e-8;
 29 const int inf  = 0x3f3f3f3f;
 30 const int maxk = 5000;
 31 const int maxn = 5000;
 32 
 33 int N, K;
 34 
 35 struct DLX {
 36     int n, m, size, fin;
 37     int U[maxk], D[maxk], L[maxk], R[maxk];
 38     int C[maxk];
 39 
 40     int head[65];
 41     int S[65];
 42     bool vis[maxk];
 43 
 44     void init( int _n, int _m )
 45     {
 46         n = _n; m = _m;
 47         for ( int i = 0; i <= m; i++ )
 48         {
 49             U[i] = D[i] = i;
 50             L[i] = i-1;
 51             R[i] = i+1;
 52             S[i] = 0;
 53         }
 54         L[0] = m; R[m] = 0;
 55         size = m;
 56         memset( head, -1, sizeof(head) );
 57     }
 58 
 59     void link( int r, int c )
 60     {
 61         size++;
 62         C[size] = c;
 63         S[c]++;
 64 
 65         D[size] = D[c];
 66         U[size] = c;
 67         U[D[c]] = size;
 68         D[c] = size;
 69 
 70         if ( head[r] < 0 )
 71             head[r] = L[size] = R[size] = size;
 72         else
 73         {
 74             R[size] = R[head[r]];
 75             L[R[size]] = size;
 76             L[size] = head[r];
 77             R[head[r]] = size;
 78         }
 79     }
 80 
 81     void remove( int id )
 82     {
 83         for ( int i = D[id]; i != id; i = D[i] )
 84         {
 85             L[R[i]] = L[i];
 86             R[L[i]] = R[i];
 87         }
 88     }
 89 
 90     void resume( int id )
 91     {
 92         for ( int i = D[id]; i != id; i = D[i] )
 93             L[R[i]] = R[L[i]] = i;
 94     }
 95 
 96     int h()
 97     {
 98         int sum = 0;
 99         memset( vis, 0, sizeof(vis) );
100         for ( int i = R[0]; i != 0; i = R[i] )
101             if (!vis[i])
102             {
103                 sum++;
104                 for ( int j = D[i]; j != i; j = D[j] )
105                     for ( int k = R[j]; k != j; k = R[k] )
106                         vis[C[k]] = 1;
107             }
108         return sum;
109     }
110 
111     void dance( int k )
112     {
113         int mark, mmin = inf;
114         int tmp = k + h();
115         if ( tmp >= fin || tmp > K )
116             return;
117         if ( R[0] == 0 )
118         {
119             if ( k < fin )
120                 fin = k;
121             return;
122         }
123 
124         for ( int i = R[0]; i != 0; i = R[i] )
125             if ( mmin > S[i] )
126             {
127                 mmin = S[i];
128                 mark = i;
129             }
130 
131         for ( int i = D[mark]; i != mark; i = D[i] )
132         {
133             remove(i);
134             for ( int j = R[i]; j != i; j = R[j] ) remove(j);
135             dance(k+1);
136             for ( int j = R[i]; j != i; j = R[j] ) resume(j);
137             resume(i);
138         }
139     }
140 }dlx;
141 
142 int cnt;
143 int g[62][2];
144 
145 struct mmap {
146     int x, y;
147     LL dist;
148     bool operator < ( const mmap &a ) const
149         { return dist < a.dist; }
150 }node[62*62];
151 
152 LL getdist( int i, int j )
153 {
154     LL x = abs(g[i][0]-g[j][0]);
155     LL y = abs(g[i][1]-g[j][1]);
156     return x+y;
157 }
158 
159 void init( int n )
160 {
161     cnt = 0;
162     for( int i = 1; i <= n; i++ )
163         scanf("%d %d", &g[i][0], &g[i][1] );
164     for ( int i = 1; i <= n; i++ )
165         for ( int j = i; j <= n; j++ )
166         {
167             node[cnt].x = i; node[cnt].y = j;
168             node[cnt++].dist = getdist(i,j);
169         }
170     sort(node, node+cnt);
171 }
172 
173 bool judge( int n, int k, LL mid )
174 {
175     dlx.init(n, n); dlx.fin = k+1;
176     
177     for ( int i = 0; i < cnt; i++ )
178     {
179         if ( node[i].dist > mid ) break;
180 
181         dlx.link( node[i].x, node[i].y );
182         if ( node[i].x != node[i].y )
183             dlx.link( node[i].y, node[i].x );
184     }
185         
186     dlx.dance(0);
187     if ( dlx.fin <= k )
188         return true;
189     else
190         return false;
191 }
192 
193 LL solve( int n, int k )
194 {
195     LL mid, lhs = 0, rhs = cnt;
196     while ( lhs <= rhs )
197     {
198         mid = (lhs+rhs)>>1;
199         if ( judge(n,k,node[mid].dist) )
200             rhs = mid-1;
201         else
202             lhs = mid+1;
203     }
204 
205     if ( judge(n,k,node[lhs].dist) )
206         return node[lhs].dist;
207     else
208         return node[rhs].dist;
209 }
210 
211 int main()
212 {
213     //freopen("F:\\cpp\\test.txt", "r", stdin );
214 
215     int T; cin >> T;
216     int n, k, cnt = 1;
217     while (T--)
218     {
219         scanf("%d %d", &n, &k);
220         N = n; K = k;
221         init(n);
222         printf("Case #%d: %lld\n", cnt++, solve(n,k));
223     }
224 
225     return 0;
226 }
View Code

   7.ZOJ 3122

  16个数字的数独,和9个数字的数独其实一样,这次加了注释,终于理解了...然后dlx范围老是调不好

  1 #include <iostream>
  2 #include <string.h>
  3 #include <cstdio>
  4 #include <vector>
  5 #include <string>
  6 #include <algorithm>
  7 #include <math.h>
  8 #include <time.h>
  9 
 10 #define SIGMA_SIZE 26
 11 #define lson rt<<1
 12 #define rson rt<<1|1
 13 #pragma warning ( disable : 4996 )
 14 
 15 using namespace std;
 16 typedef long long LL;
 17 inline LL LMax(LL a,LL b)      { return a>b?a:b; }
 18 inline LL LMin(LL a,LL b)      { return a>b?b:a; }
 19 inline int Max(int a,int b)    { return a>b?a:b; }
 20 inline int Min(int a,int b)       { return a>b?b:a; }
 21 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); }
 22 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; }  //a*b = gcd*lcm
 23 const LL INF = 0x3f3f3f3f3f3f3f3f;
 24 const LL mod  = 1000000007;
 25 const double eps = 1e-8;
 26 const int inf  = 0x3f3f3f3f;
 27 const int maxk = 1e5;
 28 const int maxn = 1030;
 29 
 30 //行:16x16x16=4096表示每个格子有16种选择
 31 //列:(16x16)x3=768,表示16行16列16小块每个各有16种数字单独存在
 32 //列:还要加上768+16x16=1024,表示每个格子只能有一个数字
 33 
 34 struct DLX {
 35     int n, m, size, fin;
 36     int U[maxk], D[maxk], L[maxk], R[maxk];//上下左右
 37     int head[maxk], S[maxk];                //分别存每一行第一个1的点的标号和每一列1的个数
 38     int row[maxk], col[maxk], ans[maxk];    //row,col表示第size个点在哪一行/列
 39 
 40 
 41     void init( int _n, int _m )
 42     {
 43         n = _n; m = _m;
 44         for ( int i = 0; i <= m; i++ )    //初始化第一行(人为增加的虚拟行)
 45         {
 46             S[i] = 0;
 47             U[i] = D[i] = i;
 48             L[i] = i-1;
 49             R[i] = i+1;
 50         }
 51         R[m] = 0; L[0] = m;        //第一行的最后一个元素指向第一个
 52         size = m;                //从m开始以后都是普通节点
 53         memset( head, -1, sizeof(head) );
 54         head[0] = 0;
 55     }
 56 
 57     void link( int r, int c )
 58     {
 59         size++;                    //得到新的点标号
 60         col[size] = c;            //第size个点在第c列
 61         row[size] = r;            //第size个点在第r行
 62         S[c]++;                    //第c列1的个数+1
 63 
 64                                    //组成一个环,和下面左右一样的插法
 65         D[size] = D[c];            
 66         U[size] = c;            
 67         U[D[c]] = size;            
 68         D[c] = size;        
 69 
 70         //如果该行没有为1的节点
 71         if ( head[r] < 0 ) head[r] = L[size] = R[size] = size;
 72         else
 73         {
 74             //组成一个环,插在head[r]和head[r]右边那个元素中间
 75             R[size] = R[head[r]];        
 76             L[R[size]] = size;
 77             L[size] = head[r];
 78             R[head[r]] = size;
 79         }
 80     }
 81 
 82     void remove( int c )   //删除列c及其所在行
 83     {
 84         L[R[c]] = L[c]; R[L[c]] = R[c];                //c的左右两个节点互相连接
 85         for ( int i = D[c]; i != c; i = D[i] )        //屏蔽c列
 86             for ( int j = R[i]; j != i; j = R[j] )
 87             {
 88                 U[D[j]] = U[j];
 89                 D[U[j]] = D[j];
 90                 --S[col[j]];        //j所在的列的1的数目数减少
 91             }
 92     }
 93 
 94     void resume( int c )
 95     {
 96         for ( int i = U[c]; i != c; i = U[i] )
 97             for ( int j = L[i]; j != i; j = L[j] )
 98             {
 99                 U[D[j]] = D[U[j]] = j;
100                 ++S[col[j]];
101             }
102         L[R[c]] = R[L[c]] = c;
103     }
104 
105     bool dance( int d )
106     {
107         if ( R[0] == 0 ) //第0行没有节点
108         {
109             fin = d;
110             return true;
111         }
112 
113         //找出含1数目最小的一列
114         int mark = R[0];
115         for ( int i = R[0]; i != 0; i = R[i] )
116             if ( S[i] < S[mark] )
117                 mark = i;
118 
119         remove(mark);    //移除列mark的1的对应行
120         for ( int i = D[mark]; i != mark; i = D[i] )
121         {
122             ans[d] = row[i];
123             //移除该行的1的对应列
124             for ( int j = R[i]; j != i; j = R[j] )
125                 remove(col[j]);
126 
127             if ( dance(d+1) )
128                 return true;
129 
130             //倒着恢复
131             for ( int j = L[i]; j != i; j = L[j] )
132                 resume(col[j]);
133         }
134         resume(mark);
135         return false;
136     }
137 }dlx;
138 
139 char mmap[20][20];
140 char sudoku[20][20];
141 struct node {
142     int x, y, k;
143 }e[maxk];
144 
145 
146 void init()
147 {
148     //4096行,1024列
149     dlx.init(4096,1024);
150     int row = 0;
151 
152     for ( int i = 1; i <= 16; i++ )
153         for ( int j = 1; j <= 16; j++ )
154         {
155             if ( mmap[i][j] == '-' )
156                 for (int k = 1; k <= 16; k++ )
157                 {
158                     row++;
159                     dlx.link(row, (i-1)*16+j );                            //第i行第j个格子已经填了数字
160                     dlx.link(row, 256+(i-1)*16+k);                        //第i行已经填了数字k
161                     dlx.link(row, 512+(j-1)*16+k);                        //第j列已经填了数字k
162                     dlx.link(row, 768+(((i-1)/4)*4 + (j-1)/4)*16+k);    //第xxx个格子已经填了数字k
163                     e[row].x = i; e[row].y = j; e[row].k = k;
164                 }
165             else
166             {
167                 row++;
168                 int k = mmap[i][j] - 'A' + 1;
169                 dlx.link(row, (i-1)*16+j);                
170                 dlx.link(row, 256+(i-1)*16+k);
171                 dlx.link(row, 512+(j-1)*16+k);
172                 dlx.link(row, 768+(((i-1)/4)*4 + (j-1)/4)*16+k);
173                 e[row].x = i; e[row].y = j; e[row].k = k;
174             }
175         }
176 }
177 
178 int main()
179 {
180     //freopen("F:\\cpp\\test.txt", "r", stdin );
181 
182     int cnt = 0;
183     while (1)
184     {
185         if ( ~scanf("%s", mmap[1]+1) ) 
186         { 
187             for ( int i = 2; i <= 16; i++ )
188                 scanf("%s", mmap[i]+1);
189             
190             if (cnt++)
191                  printf("\n"); 
192 
193             init();
194             dlx.dance(0);
195 
196             int tmp;
197             for ( int i = 0; i < dlx.fin; i++ )
198             {
199                 tmp = dlx.ans[i];
200                 sudoku[e[tmp].x-1][e[tmp].y-1] = e[tmp].k + 'A' - 1;
201                 sudoku[e[tmp].x-1][16] = '\0';
202             }
203             for ( int i = 0; i < 16; i++ )
204                 printf("%s\n", sudoku[i]);
205         }
206         else
207             break;
208     }
209 }
View Code

 

posted @ 2018-05-09 21:22  LBNOQYX  阅读(908)  评论(0编辑  收藏  举报