• 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( "
    " );
    167             //continue;
    168         }
    169         else
    170             printf("NO
    ");
    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
    ", 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
    ", 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
    ", (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
    ", 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] = '';
    212         printf("%s
    ", 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
    ", 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("
    "); 
    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] = '';
    202             }
    203             for ( int i = 0; i < 16; i++ )
    204                 printf("%s
    ", sudoku[i]);
    205         }
    206         else
    207             break;
    208     }
    209 }
    View Code
  • 相关阅读:
    git或gitee 提交代码到远程仓库
    gitee 创建代码仓库,并提交本地代码
    Logback 实现日志链路追踪
    navicat 查看,设计并导出数据库 ER图
    Jackson 使用 @JsonFormat 注解进行时间格式化
    Redis 缓存常见问题
    jedis 与 redission 实现分布式锁
    Redis 集群模式搭建
    Redis 哨兵模式高可用
    Notepad++ 正则表达式提取信息
  • 原文地址:https://www.cnblogs.com/chaoswr/p/9016739.html
Copyright © 2020-2023  润新知