kuangbin带我飞QAQ DLX之一脸懵逼
1. hust 1017 DLX精确覆盖 模板题
勉强写了注释,但还是一脸懵逼,感觉插入方式明显有问题但又不知道哪里不对而且好像能得出正确结果真是奇了怪了
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e5+;
- const int maxn = 1e4+;
- //第一行为虚拟行,是人为加上的,一共有m+1个点(第一个点独立于整个矩阵)
- //而后加入的值为1的点标号用size表示
- //即第一行一共m+1个点,所以size先从0~m,之后每加入一个为1的点,size++
- //大部分数组X都用X[size]来标识标号为size的点的信息
- struct DLX {
- int n, m, size, fin;
- int U[maxn], D[maxn], L[maxn], R[maxn];//上下左右
- int head[maxn], S[maxn]; //分别存每一行第一个1的点的标号和每一列1的个数
- int row[maxn], col[maxn], ans[maxn]; //row,col表示第size个点在哪一行/列
- void init( int _n, int _m )
- {
- n = _n; m = _m;
- for ( int i = ; i <= m; i++ ) //初始化第一行(人为增加的虚拟行)
- {
- S[i] = ;
- U[i] = D[i] = i;
- L[i] = i-;
- R[i] = i+;
- }
- R[m] = ; L[] = m; //第一行的最后一个元素指向第一个
- size = m; //从m开始以后都是普通节点
- memset( head, -, sizeof(head) );
- head[] = ;
- }
- void link( int r, int c )
- {
- size++; //得到新的点标号
- col[size] = c; //第size个点在第c列
- row[size] = r; //第size个点在第r行
- S[c]++; //第c列1的个数+1
- //组成一个环,和下面左右一样的插法
- D[size] = D[c];
- U[size] = c;
- U[D[c]] = size;
- D[c] = size;
- //如果该行没有为1的节点
- if ( head[r] < ) head[r] = L[size] = R[size] = size;
- else
- {
- //组成一个环,插在head[r]和head[r]右边那个元素中间
- R[size] = R[head[r]];
- L[R[size]] = size;
- L[size] = head[r];
- R[head[r]] = size;
- }
- }
- void remove( int c ) //删除列c及其所在行
- {
- L[R[c]] = L[c]; R[L[c]] = R[c]; //c的左右两个节点互相连接
- for ( int i = D[c]; i != c; i = D[i] ) //屏蔽c列
- for ( int j = R[i]; j != i; j = R[j] )
- {
- U[D[j]] = U[j];
- D[U[j]] = D[j];
- --S[col[j]]; //j所在的列的1的数目数减少
- }
- }
- void resume( int c )
- {
- for ( int i = U[c]; i != c; i = U[i] )
- for ( int j = L[i]; j != i; j = L[j] )
- {
- U[D[j]] = D[U[j]] = j;
- ++S[col[j]];
- }
- L[R[c]] = R[L[c]] = c;
- }
- bool dance( int d )
- {
- if ( R[] == ) //第0行没有节点
- {
- fin = d;
- return true;
- }
- //找出含1数目最小的一列
- int mark = R[];
- for ( int i = R[]; i != ; i = R[i] )
- if ( S[i] < S[mark] )
- mark = i;
- remove(mark); //移除列mark的1的对应行
- for ( int i = D[mark]; i != mark; i = D[i] )
- {
- ans[d] = row[i];
- //移除该行的1的对应列
- for ( int j = R[i]; j != i; j = R[j] )
- remove(col[j]);
- if ( dance(d+) )
- return true;
- //倒着恢复
- for ( int j = L[i]; j != i; j = L[j] )
- resume(col[j]);
- }
- resume(mark);
- return false;
- }
- }dlx;
- int main()
- {
- //freopen("F:\\cpp\\test.txt","r",stdin);
- int n, m;
- while ( ~scanf("%d %d", &n, &m) )
- {
- dlx.init(n,m);
- for ( int i = ; i <= n; i++ )
- {
- int num, j;
- scanf("%d",&num);
- while (num--)
- {
- scanf("%d",&j);
- dlx.link(i,j);
- }
- }
- if ( dlx.dance() )
- {
- printf( "%d", dlx.fin );
- for ( int i = ; i < dlx.fin; i++ )
- printf( " %d", dlx.ans[i] );
- printf( "\n" );
- //continue;
- }
- else
- printf("NO\n");
- }
- return ;
- }
2. ZOJ 3209 矩阵映射DLX精确覆盖
给一个大矩阵和p个小矩阵,问在p个小矩阵中能否取若干个使它们覆盖整个大矩阵,并且小矩阵间两两互不覆盖。
把大矩阵分为1-n*m个小块(就是横竖切割n和m次),则题目的要求就变成了每个小块都要被一个且仅能有一个小矩阵覆盖,然后就是映射了,因为每个小矩阵能覆盖1~n*m这么多编号小块中的某些块,那么我们让每个小矩阵为1行,并设n*m列,则题目就变成p行n*m列的矩阵对其求精确覆盖了
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e5+;
- const int maxn = 1e5;
- struct DLX {
- int n, m, size, fin;
- int U[maxn], D[maxn], L[maxn], R[maxn]; //上下左右
- int head[maxn], S[maxn]; //分别存每一行第一个1的点的标号和每一列1的个数
- int row[maxn], col[maxn], ans[maxn]; //row,col表示第size个点在哪一行/列
- void init( int _n, int _m )
- {
- n = _n; m = _m;
- for ( int i = ; i <= m; i++ ) //初始化第一行(人为增加的虚拟行)
- {
- S[i] = ;
- U[i] = D[i] = i;
- L[i] = i-;
- R[i] = i+;
- }
- R[m] = ; L[] = m; //第一行的最后一个元素指向第一个
- fin = -; size = m; //从m开始以后都是普通节点
- memset( head, -, sizeof(head) );
- }
- void link( int r, int c )
- {
- size++; //得到新的点标号
- col[size] = c; //第size个点在第c列
- row[size] = r; //第size个点在第r行
- S[c]++; //第c列1的个数+1
- //组成一个环,和下面左右一样的插法
- D[size] = D[c];
- U[size] = c;
- U[D[c]] = size;
- D[c] = size;
- //如果该行没有为1的节点
- if ( head[r] < ) head[r] = L[size] = R[size] = size;
- else
- {
- //组成一个环,插在head[r]和head[r]右边那个元素中间
- R[size] = R[head[r]];
- L[R[size]] = size;
- L[size] = head[r];
- R[head[r]] = size;
- }
- }
- void remove( int c ) //删除列c及其所在行
- {
- L[R[c]] = L[c]; R[L[c]] = R[c]; //c的左右两个节点互相连接
- for ( int i = D[c]; i != c; i = D[i] ) //屏蔽c列
- for ( int j = R[i]; j != i; j = R[j] )
- {
- U[D[j]] = U[j];
- D[U[j]] = D[j];
- --S[col[j]]; //j所在的列的1的数目数减少
- }
- }
- void resume( int c )
- {
- for ( int i = U[c]; i != c; i = U[i] )
- for ( int j = L[i]; j != i; j = L[j] )
- {
- U[D[j]] = D[U[j]] = j;
- ++S[col[j]];
- }
- L[R[c]] = R[L[c]] = c;
- }
- void dance( int d )
- {
- if ( fin != - && fin <= d )
- return;
- if ( R[] == ) //第0行没有节点
- {
- fin = d;
- return;
- }
- //找出含1数目最小的一列
- int mark = R[];
- for ( int i = R[]; i != ; i = R[i] )
- if ( S[i] < S[mark] )
- mark = i;
- remove(mark); //移除列mark的1的对应行
- for ( int i = D[mark]; i != mark; i = D[i] )
- {
- ans[d] = row[i];
- //移除该行的1的对应列
- for ( int j = R[i]; j != i; j = R[j] )
- remove(col[j]);
- dance(d+);
- //倒着恢复
- for ( int j = L[i]; j != i; j = L[j] )
- resume(col[j]);
- }
- resume(mark);
- return;
- }
- }dlx;
- int pos[][];
- int main()
- {
- freopen("F:\\cpp\\test.txt","r",stdin);
- int n, m, p;
- int x1, x2, y1, y2;
- int T; cin >> T;
- while (T--)
- {
- scanf("%d %d %d", &n, &m, &p);
- dlx.init(p, n*m);
- int id = ;
- for ( int i = ; i <= n; i++ )
- for ( int j = ; j <= m; j++ )
- pos[i][j] = id++;
- for ( int r = ; r <= p; r++ )
- {
- scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
- //注意对应的规则
- for ( int i = x1+; i <= x2; i++ )
- for ( int j = y1+; j <= y2; j++ )
- dlx.link( r, pos[i][j] );
- }
- dlx.dance();
- printf("%d\n", dlx.fin);
- }
- return ;
- }
懒得修改了...直接贴另一种返回
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e5+;
- const int maxn = 1e5;
- struct DLX {
- int n, m, size, fin;
- int U[maxn], D[maxn], L[maxn], R[maxn]; //上下左右
- int head[maxn], S[maxn]; //分别存每一行第一个1的点的标号和每一列1的个数
- int row[maxn], col[maxn], ans[maxn]; //row,col表示第size个点在哪一行/列
- void init( int _n, int _m )
- {
- n = _n; m = _m;
- for ( int i = ; i <= m; i++ ) //初始化第一行(人为增加的虚拟行)
- {
- S[i] = ;
- U[i] = D[i] = i;
- L[i] = i-;
- R[i] = i+;
- }
- R[m] = ; L[] = m; //第一行的最后一个元素指向第一个
- fin = -; size = m; //从m开始以后都是普通节点
- memset( head, -, sizeof(head) );
- }
- void link( int r, int c )
- {
- size++; //得到新的点标号
- col[size] = c; //第size个点在第c列
- row[size] = r; //第size个点在第r行
- S[c]++; //第c列1的个数+1
- //组成一个环,和下面左右一样的插法
- D[size] = D[c];
- U[size] = c;
- U[D[c]] = size;
- D[c] = size;
- //如果该行没有为1的节点
- if ( head[r] < ) head[r] = L[size] = R[size] = size;
- else
- {
- //组成一个环,插在head[r]和head[r]右边那个元素中间
- R[size] = R[head[r]];
- L[R[size]] = size;
- L[size] = head[r];
- R[head[r]] = size;
- }
- }
- void remove( int c ) //删除列c及其所在行
- {
- L[R[c]] = L[c]; R[L[c]] = R[c]; //c的左右两个节点互相连接
- for ( int i = D[c]; i != c; i = D[i] ) //屏蔽c列
- for ( int j = R[i]; j != i; j = R[j] )
- {
- U[D[j]] = U[j];
- D[U[j]] = D[j];
- --S[col[j]]; //j所在的列的1的数目数减少
- }
- }
- void resume( int c )
- {
- for ( int i = U[c]; i != c; i = U[i] )
- for ( int j = L[i]; j != i; j = L[j] )
- {
- U[D[j]] = D[U[j]] = j;
- ++S[col[j]];
- }
- L[R[c]] = R[L[c]] = c;
- }
- bool dance( int d )
- {
- if ( fin != - && fin <= d )
- return false;
- if ( R[] == ) //第0行没有节点
- {
- fin = d;
- return true;
- }
- //找出含1数目最小的一列
- int mark = R[];
- for ( int i = R[]; i != ; i = R[i] )
- if ( S[i] < S[mark] )
- mark = i;
- remove(mark); //移除列mark的1的对应行
- for ( int i = D[mark]; i != mark; i = D[i] )
- {
- ans[d] = row[i];
- //移除该行的1的对应列
- for ( int j = R[i]; j != i; j = R[j] )
- remove(col[j]);
- dance(d+);
- //倒着恢复
- for ( int j = L[i]; j != i; j = L[j] )
- resume(col[j]);
- }
- resume(mark);
- return false;
- }
- }dlx;
- int pos[][];
- int main()
- {
- freopen("F:\\cpp\\test.txt","r",stdin);
- int n, m, p;
- int x1, x2, y1, y2;
- int T; cin >> T;
- while (T--)
- {
- scanf("%d %d %d", &n, &m, &p);
- dlx.init(p, n*m);
- int id = ;
- for ( int i = ; i <= n; i++ )
- for ( int j = ; j <= m; j++ )
- pos[i][j] = id++;
- for ( int r = ; r <= p; r++ )
- {
- scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
- //注意对应的规则
- for ( int i = x1+; i <= x2; i++ )
- for ( int j = y1+; j <= y2; j++ )
- dlx.link( r, pos[i][j] );
- }
- dlx.dance();
- printf("%d\n", dlx.fin);
- }
- return ;
- }
3.HDU 2295 圆形重复覆盖+二分
一脸懵逼逼逼....如果说之前那个模板还勉强看的懂...这个就完全懵逼了(还非常容易写错)。题目比较简单就不说了
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const double eps = 1e-;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e4;
- const int maxn = ;
- struct DLX {
- int n, m, size, fin;
- int U[maxk], D[maxk], L[maxk], R[maxk];
- int C[maxk];
- int head[maxk];
- int S[maxk];
- bool vis[maxk];
- void init( int _n, int _m )
- {
- n = _n; m = _m;
- for ( int i = ; i <= m; i++ )
- {
- U[i] = D[i] = i;
- L[i] = i-;
- R[i] = i+;
- S[i] = ;
- }
- L[] = m; R[m] = ;
- size = m;
- memset( head, -, sizeof(head) );
- }
- void link( int r, int c )
- {
- size++;
- C[size] = c;
- S[c]++;
- D[size] = D[c];
- U[size] = c;
- U[D[c]] = size;
- D[c] = size;
- if ( head[r] < )
- head[r] = L[size] = R[size] = size;
- else
- {
- R[size] = R[head[r]];
- L[R[size]] = size;
- L[size] = head[r];
- R[head[r]] = size;
- }
- }
- void remove( int id )
- {
- for ( int i = D[id]; i != id; i = D[i] )
- {
- L[R[i]] = L[i];
- R[L[i]] = R[i];
- }
- }
- void resume( int id )
- {
- for ( int i = D[id]; i != id; i = D[i] )
- L[R[i]] = R[L[i]] = i;
- }
- int h()
- {
- int sum = ;
- memset( vis, , sizeof(vis) );
- for ( int i = R[]; i != ; i = R[i] )
- if (!vis[i])
- {
- sum++;
- for ( int j = D[i]; j != i; j = D[j] )
- for ( int k = R[j]; k != j; k = R[k] )
- vis[C[k]] = ;
- }
- return sum;
- }
- void dance( int k )
- {
- int mark, mmin = inf;
- if ( k + h() >= fin )
- return;
- if ( R[] == )
- {
- if ( k < fin )
- fin = k;
- return;
- }
- for ( int i = R[]; i != ; i = R[i] )
- if ( mmin > S[i] )
- {
- mmin = S[i];
- mark = i;
- }
- for ( int i = D[mark]; i != mark; i = D[i] )
- {
- remove(i);
- for ( int j = R[i]; j != i; j = R[j] ) remove(j);
- dance(k+);
- for ( int j = R[i]; j != i; j = R[j] ) resume(j);
- resume(i);
- }
- }
- }dlx;
- double mmap[maxn][];
- double cir[maxn][];
- void init( int n, int m )
- {
- for ( int i = ; i <= n; i++ )
- scanf("%lf %lf", &mmap[i][], &mmap[i][]);
- for ( int i = ; i <= m; i++ )
- scanf("%lf %lf", &cir[i][], &cir[i][]);
- }
- double getdis( int i, int j )
- {
- double a = mmap[i][] - cir[j][];
- double b = mmap[i][] - cir[j][];
- a *= a; b *= b;
- return sqrt(a+b);
- }
- bool judge( int n, int m, int k, double r )
- {
- dlx.init(m, n); dlx.fin = inf;
- for ( int i = ; i <= n; i++ )
- for ( int j = ; j <= m; j++ )
- {
- if ( r >= getdis(i,j) )
- dlx.link(j,i);
- }
- dlx.dance();
- if ( dlx.fin <= k ) return ;
- else return ;
- }
- int main()
- {
- #ifdef local
- freopen("F:\\cpp\\test.txt","r",stdin);
- #endif
- int n, m, k;
- int T; cin >> T;
- while (T--)
- {
- scanf("%d %d %d", &n, &m, &k);
- init(n,m);
- double mid, lhs = 0.0, rhs = 1000.0;
- while ( rhs - lhs > eps )
- {
- mid = (lhs+rhs) / ;
- if ( judge(n,m,k,mid) )
- rhs = mid;
- else
- lhs = mid;
- }
- printf("%.6lf\n", (lhs+rhs)/);
- }
- return ;
- }
4.FZU 1686 矩形重复覆盖
原来DLX主要是考察建模啊,模板实在不想每次都打一遍了...直接ctrl+c
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const double eps = 1e-;
- const int inf = 0x3f3f3f3f;
- const int maxk = ;
- const int maxn = ;
- struct DLX {
- int n, m, size, fin;
- int U[maxk], D[maxk], L[maxk], R[maxk];
- int C[maxk];
- int head[maxk];
- int S[maxk];
- bool vis[maxk];
- void init( int _n, int _m )
- {
- n = _n; m = _m;
- for ( int i = ; i <= m; i++ )
- {
- U[i] = D[i] = i;
- L[i] = i-;
- R[i] = i+;
- S[i] = ;
- }
- L[] = m; R[m] = ;
- fin = inf; size = m;
- memset( head, -, sizeof(head) );
- }
- void link( int r, int c )
- {
- size++;
- C[size] = c;
- S[c]++;
- D[size] = D[c];
- U[size] = c;
- U[D[c]] = size;
- D[c] = size;
- if ( head[r] < )
- head[r] = L[size] = R[size] = size;
- else
- {
- R[size] = R[head[r]];
- L[R[size]] = size;
- L[size] = head[r];
- R[head[r]] = size;
- }
- }
- void remove( int id )
- {
- for ( int i = D[id]; i != id; i = D[i] )
- {
- L[R[i]] = L[i];
- R[L[i]] = R[i];
- }
- }
- void resume( int id )
- {
- for ( int i = D[id]; i != id; i = D[i] )
- L[R[i]] = R[L[i]] = i;
- }
- int h()
- {
- int sum = ;
- memset( vis, , sizeof(vis) );
- for ( int i = R[]; i != ; i = R[i] )
- if (!vis[i])
- {
- sum++;
- for ( int j = D[i]; j != i; j = D[j] )
- for ( int k = R[j]; k != j; k = R[k] )
- vis[C[k]] = ;
- }
- return sum;
- }
- void dance( int k )
- {
- int mark, mmin = inf;
- if ( k + h() >= fin )
- return;
- if ( R[] == )
- {
- if ( k < fin )
- fin = k;
- return;
- }
- for ( int i = R[]; i != ; i = R[i] )
- if ( mmin > S[i] )
- {
- mmin = S[i];
- mark = i;
- }
- for ( int i = D[mark]; i != mark; i = D[i] )
- {
- remove(i);
- for ( int j = R[i]; j != i; j = R[j] ) remove(j);
- dance(k+);
- for ( int j = R[i]; j != i; j = R[j] ) resume(j);
- resume(i);
- }
- }
- }dlx;
- int mmap[][], g[][];
- void init()
- {
- memset( mmap, , sizeof(mmap) );
- memset( g, , sizeof(g) );
- }
- int main()
- {
- #ifdef local
- freopen("F:\\cpp\\test.txt","r",stdin);
- #endif
- int R, C, r, c;
- while ( ~scanf("%d %d", &R, &C) )
- {
- init();
- int cnt = ;
- for ( int i = ; i <= R; i++ )
- for (int j = ; j <= C; j++)
- {
- scanf("%d", &mmap[i][j]);
- if ( mmap[i][j] )
- g[i][j] = ++cnt;
- }
- scanf("%d %d", &r, &c);
- dlx.init( (R-r+)*(C-c+), cnt );
- cnt = ;
- for ( int i = ; i+r- <= R; i++ )
- for ( int j = ; j+c- <= C; j++ )
- {
- for ( int a = i; a <= i+r-; a++ )
- for ( int b = j; b <= j + c - ; b++ )
- if (g[a][b])
- dlx.link(cnt, g[a][b]);
- cnt++;
- }
- dlx.dance();
- printf("%d\n", dlx.fin);
- }
- return ;
- }
5.POJ 3074
求解数独....emmmm我得好好理解下才行
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #include <time.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const double eps = 1e-;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e8;
- const int maxn = ;
- struct node {
- int x, y, k;
- }e[];
- struct DLX {
- int n, m, size, fin;
- int U[maxn], D[maxn], L[maxn], R[maxn];//上下左右
- int head[maxn], S[maxn]; //分别存每一行第一个1的点的标号和每一列1的个数
- int row[maxn], col[maxn], ans[maxn]; //row,col表示第size个点在哪一行/列
- void init( int _n, int _m )
- {
- n = _n; m = _m;
- for ( int i = ; i <= m; i++ ) //初始化第一行(人为增加的虚拟行)
- {
- S[i] = ;
- U[i] = D[i] = i;
- L[i] = i-;
- R[i] = i+;
- }
- R[m] = ; L[] = m; //第一行的最后一个元素指向第一个
- size = m; //从m开始以后都是普通节点
- memset( head, -, sizeof(head) );
- head[] = ;
- }
- void link( int r, int c )
- {
- size++; //得到新的点标号
- col[size] = c; //第size个点在第c列
- row[size] = r; //第size个点在第r行
- S[c]++; //第c列1的个数+1
- //组成一个环,和下面左右一样的插法
- D[size] = D[c];
- U[size] = c;
- U[D[c]] = size;
- D[c] = size;
- //如果该行没有为1的节点
- if ( head[r] < ) head[r] = L[size] = R[size] = size;
- else
- {
- //组成一个环,插在head[r]和head[r]右边那个元素中间
- R[size] = R[head[r]];
- L[R[size]] = size;
- L[size] = head[r];
- R[head[r]] = size;
- }
- }
- void remove( int c ) //删除列c及其所在行
- {
- L[R[c]] = L[c]; R[L[c]] = R[c]; //c的左右两个节点互相连接
- for ( int i = D[c]; i != c; i = D[i] ) //屏蔽c列
- for ( int j = R[i]; j != i; j = R[j] )
- {
- U[D[j]] = U[j];
- D[U[j]] = D[j];
- --S[col[j]]; //j所在的列的1的数目数减少
- }
- }
- void resume( int c )
- {
- for ( int i = U[c]; i != c; i = U[i] )
- for ( int j = L[i]; j != i; j = L[j] )
- {
- U[D[j]] = D[U[j]] = j;
- ++S[col[j]];
- }
- L[R[c]] = R[L[c]] = c;
- }
- bool dance( int d )
- {
- if ( R[] == ) //第0行没有节点
- {
- fin = d;
- return true;
- }
- //找出含1数目最小的一列
- int mark = R[];
- for ( int i = R[]; i != ; i = R[i] )
- if ( S[i] < S[mark] )
- mark = i;
- remove(mark); //移除列mark的1的对应行
- for ( int i = D[mark]; i != mark; i = D[i] )
- {
- ans[d] = row[i];
- //移除该行的1的对应列
- for ( int j = R[i]; j != i; j = R[j] )
- remove(col[j]);
- if ( dance(d+) )
- return true;
- //倒着恢复
- for ( int j = L[i]; j != i; j = L[j] )
- resume(col[j]);
- }
- resume(mark);
- return false;
- }
- }dlx;
- int mmap[][];
- char sudoku[];
- void read()
- {
- dlx.init(,);
- int row = ;
- for ( int i = ; i <= ; i++ )
- for ( int j = ; j <= ; j++ )
- {
- if ( !mmap[i][j] )
- {
- for ( int k = ; k <= ; k++ )
- {
- ++row;
- dlx.link(row, (i-)*+j);
- dlx.link(row, +(i-)*+k);
- dlx.link(row, +(j-)*+k);
- dlx.link(row,+(((i-)/)*+(j+)/-)*+k);
- e[row].x = i; e[row].y = j; e[row].k = k;
- }
- }
- else
- {
- ++row;
- int k = mmap[i][j];
- dlx.link(row, (i-)*+j);
- dlx.link(row, +(i-)*+k);
- dlx.link(row, +(j-)*+k);
- dlx.link(row, +(((i-)/)*+(j+)/-)*+k);
- e[row].x = i; e[row].y = j; e[row].k = k;
- }
- }
- }
- void init()
- {
- int t = ;
- for ( int i = ; i <= ; i++ )
- for ( int j = ; j <= ; j++ )
- {
- if ( sudoku[++t] != '.' )
- mmap[i][j] = sudoku[t] - '';
- else
- mmap[i][j] = ;
- }
- read();
- }
- int main()
- {
- //freopen("F:\\cpp\\test.txt", "r", stdin );
- while ( ~scanf("%s", sudoku+) )
- {
- if (sudoku[] == 'e') break;
- init();
- dlx.dance();
- for ( int i = ; i < dlx.fin; i++ )
- {
- int tmp = dlx.ans[i];
- sudoku[(e[tmp].x-)* + e[tmp].y-] = ''+e[tmp].k;
- }
- sudoku[dlx.fin] = '\0';
- printf("%s\n", sudoku);
- }
- return ;
- }
6. HDU 5046
和hdu2295基本一样,有个可以优化的方法是将可行的距离排序后二分下标,如果不这样做直接二分,左右区间要到1~4e9才行,而且大概率TLE(交了一发1300ms)
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <queue>
- #include <map>
- #include <vector>
- #include <string>
- #include <cstring>
- #include <algorithm>
- #include <math.h>
- #include <time.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const double eps = 1e-;
- const int inf = 0x3f3f3f3f;
- const int maxk = ;
- const int maxn = ;
- int N, K;
- struct DLX {
- int n, m, size, fin;
- int U[maxk], D[maxk], L[maxk], R[maxk];
- int C[maxk];
- int head[];
- int S[];
- bool vis[maxk];
- void init( int _n, int _m )
- {
- n = _n; m = _m;
- for ( int i = ; i <= m; i++ )
- {
- U[i] = D[i] = i;
- L[i] = i-;
- R[i] = i+;
- S[i] = ;
- }
- L[] = m; R[m] = ;
- size = m;
- memset( head, -, sizeof(head) );
- }
- void link( int r, int c )
- {
- size++;
- C[size] = c;
- S[c]++;
- D[size] = D[c];
- U[size] = c;
- U[D[c]] = size;
- D[c] = size;
- if ( head[r] < )
- head[r] = L[size] = R[size] = size;
- else
- {
- R[size] = R[head[r]];
- L[R[size]] = size;
- L[size] = head[r];
- R[head[r]] = size;
- }
- }
- void remove( int id )
- {
- for ( int i = D[id]; i != id; i = D[i] )
- {
- L[R[i]] = L[i];
- R[L[i]] = R[i];
- }
- }
- void resume( int id )
- {
- for ( int i = D[id]; i != id; i = D[i] )
- L[R[i]] = R[L[i]] = i;
- }
- int h()
- {
- int sum = ;
- memset( vis, , sizeof(vis) );
- for ( int i = R[]; i != ; i = R[i] )
- if (!vis[i])
- {
- sum++;
- for ( int j = D[i]; j != i; j = D[j] )
- for ( int k = R[j]; k != j; k = R[k] )
- vis[C[k]] = ;
- }
- return sum;
- }
- void dance( int k )
- {
- int mark, mmin = inf;
- int tmp = k + h();
- if ( tmp >= fin || tmp > K )
- return;
- if ( R[] == )
- {
- if ( k < fin )
- fin = k;
- return;
- }
- for ( int i = R[]; i != ; i = R[i] )
- if ( mmin > S[i] )
- {
- mmin = S[i];
- mark = i;
- }
- for ( int i = D[mark]; i != mark; i = D[i] )
- {
- remove(i);
- for ( int j = R[i]; j != i; j = R[j] ) remove(j);
- dance(k+);
- for ( int j = R[i]; j != i; j = R[j] ) resume(j);
- resume(i);
- }
- }
- }dlx;
- int cnt;
- int g[][];
- struct mmap {
- int x, y;
- LL dist;
- bool operator < ( const mmap &a ) const
- { return dist < a.dist; }
- }node[*];
- LL getdist( int i, int j )
- {
- LL x = abs(g[i][]-g[j][]);
- LL y = abs(g[i][]-g[j][]);
- return x+y;
- }
- void init( int n )
- {
- cnt = ;
- for( int i = ; i <= n; i++ )
- scanf("%d %d", &g[i][], &g[i][] );
- for ( int i = ; i <= n; i++ )
- for ( int j = i; j <= n; j++ )
- {
- node[cnt].x = i; node[cnt].y = j;
- node[cnt++].dist = getdist(i,j);
- }
- sort(node, node+cnt);
- }
- bool judge( int n, int k, LL mid )
- {
- dlx.init(n, n); dlx.fin = k+;
- for ( int i = ; i < cnt; i++ )
- {
- if ( node[i].dist > mid ) break;
- dlx.link( node[i].x, node[i].y );
- if ( node[i].x != node[i].y )
- dlx.link( node[i].y, node[i].x );
- }
- dlx.dance();
- if ( dlx.fin <= k )
- return true;
- else
- return false;
- }
- LL solve( int n, int k )
- {
- LL mid, lhs = , rhs = cnt;
- while ( lhs <= rhs )
- {
- mid = (lhs+rhs)>>;
- if ( judge(n,k,node[mid].dist) )
- rhs = mid-;
- else
- lhs = mid+;
- }
- if ( judge(n,k,node[lhs].dist) )
- return node[lhs].dist;
- else
- return node[rhs].dist;
- }
- int main()
- {
- //freopen("F:\\cpp\\test.txt", "r", stdin );
- int T; cin >> T;
- int n, k, cnt = ;
- while (T--)
- {
- scanf("%d %d", &n, &k);
- N = n; K = k;
- init(n);
- printf("Case #%d: %lld\n", cnt++, solve(n,k));
- }
- return ;
- }
7.ZOJ 3122
16个数字的数独,和9个数字的数独其实一样,这次加了注释,终于理解了...然后dlx范围老是调不好
- #include <iostream>
- #include <string.h>
- #include <cstdio>
- #include <vector>
- #include <string>
- #include <algorithm>
- #include <math.h>
- #include <time.h>
- #define SIGMA_SIZE 26
- #define lson rt<<1
- #define rson rt<<1|1
- #pragma warning ( disable : 4996 )
- using namespace std;
- typedef long long LL;
- inline LL LMax(LL a,LL b) { return a>b?a:b; }
- inline LL LMin(LL a,LL b) { return a>b?b:a; }
- inline int Max(int a,int b) { return a>b?a:b; }
- inline int Min(int a,int b) { return a>b?b:a; }
- inline int gcd( int a, int b ) { return b==?a:gcd(b,a%b); }
- inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm
- const LL INF = 0x3f3f3f3f3f3f3f3f;
- const LL mod = ;
- const double eps = 1e-;
- const int inf = 0x3f3f3f3f;
- const int maxk = 1e5;
- const int maxn = ;
- //行:16x16x16=4096表示每个格子有16种选择
- //列:(16x16)x3=768,表示16行16列16小块每个各有16种数字单独存在
- //列:还要加上768+16x16=1024,表示每个格子只能有一个数字
- struct DLX {
- int n, m, size, fin;
- int U[maxk], D[maxk], L[maxk], R[maxk];//上下左右
- int head[maxk], S[maxk]; //分别存每一行第一个1的点的标号和每一列1的个数
- int row[maxk], col[maxk], ans[maxk]; //row,col表示第size个点在哪一行/列
- void init( int _n, int _m )
- {
- n = _n; m = _m;
- for ( int i = ; i <= m; i++ ) //初始化第一行(人为增加的虚拟行)
- {
- S[i] = ;
- U[i] = D[i] = i;
- L[i] = i-;
- R[i] = i+;
- }
- R[m] = ; L[] = m; //第一行的最后一个元素指向第一个
- size = m; //从m开始以后都是普通节点
- memset( head, -, sizeof(head) );
- head[] = ;
- }
- void link( int r, int c )
- {
- size++; //得到新的点标号
- col[size] = c; //第size个点在第c列
- row[size] = r; //第size个点在第r行
- S[c]++; //第c列1的个数+1
- //组成一个环,和下面左右一样的插法
- D[size] = D[c];
- U[size] = c;
- U[D[c]] = size;
- D[c] = size;
- //如果该行没有为1的节点
- if ( head[r] < ) head[r] = L[size] = R[size] = size;
- else
- {
- //组成一个环,插在head[r]和head[r]右边那个元素中间
- R[size] = R[head[r]];
- L[R[size]] = size;
- L[size] = head[r];
- R[head[r]] = size;
- }
- }
- void remove( int c ) //删除列c及其所在行
- {
- L[R[c]] = L[c]; R[L[c]] = R[c]; //c的左右两个节点互相连接
- for ( int i = D[c]; i != c; i = D[i] ) //屏蔽c列
- for ( int j = R[i]; j != i; j = R[j] )
- {
- U[D[j]] = U[j];
- D[U[j]] = D[j];
- --S[col[j]]; //j所在的列的1的数目数减少
- }
- }
- void resume( int c )
- {
- for ( int i = U[c]; i != c; i = U[i] )
- for ( int j = L[i]; j != i; j = L[j] )
- {
- U[D[j]] = D[U[j]] = j;
- ++S[col[j]];
- }
- L[R[c]] = R[L[c]] = c;
- }
- bool dance( int d )
- {
- if ( R[] == ) //第0行没有节点
- {
- fin = d;
- return true;
- }
- //找出含1数目最小的一列
- int mark = R[];
- for ( int i = R[]; i != ; i = R[i] )
- if ( S[i] < S[mark] )
- mark = i;
- remove(mark); //移除列mark的1的对应行
- for ( int i = D[mark]; i != mark; i = D[i] )
- {
- ans[d] = row[i];
- //移除该行的1的对应列
- for ( int j = R[i]; j != i; j = R[j] )
- remove(col[j]);
- if ( dance(d+) )
- return true;
- //倒着恢复
- for ( int j = L[i]; j != i; j = L[j] )
- resume(col[j]);
- }
- resume(mark);
- return false;
- }
- }dlx;
- char mmap[][];
- char sudoku[][];
- struct node {
- int x, y, k;
- }e[maxk];
- void init()
- {
- //4096行,1024列
- dlx.init(,);
- int row = ;
- for ( int i = ; i <= ; i++ )
- for ( int j = ; j <= ; j++ )
- {
- if ( mmap[i][j] == '-' )
- for (int k = ; k <= ; k++ )
- {
- row++;
- dlx.link(row, (i-)*+j ); //第i行第j个格子已经填了数字
- dlx.link(row, +(i-)*+k); //第i行已经填了数字k
- dlx.link(row, +(j-)*+k); //第j列已经填了数字k
- dlx.link(row, +(((i-)/)* + (j-)/)*+k); //第xxx个格子已经填了数字k
- e[row].x = i; e[row].y = j; e[row].k = k;
- }
- else
- {
- row++;
- int k = mmap[i][j] - 'A' + ;
- dlx.link(row, (i-)*+j);
- dlx.link(row, +(i-)*+k);
- dlx.link(row, +(j-)*+k);
- dlx.link(row, +(((i-)/)* + (j-)/)*+k);
- e[row].x = i; e[row].y = j; e[row].k = k;
- }
- }
- }
- int main()
- {
- //freopen("F:\\cpp\\test.txt", "r", stdin );
- int cnt = ;
- while ()
- {
- if ( ~scanf("%s", mmap[]+) )
- {
- for ( int i = ; i <= ; i++ )
- scanf("%s", mmap[i]+);
- if (cnt++)
- printf("\n");
- init();
- dlx.dance();
- int tmp;
- for ( int i = ; i < dlx.fin; i++ )
- {
- tmp = dlx.ans[i];
- sudoku[e[tmp].x-][e[tmp].y-] = e[tmp].k + 'A' - ;
- sudoku[e[tmp].x-][] = '\0';
- }
- for ( int i = ; i < ; i++ )
- printf("%s\n", sudoku[i]);
- }
- else
- break;
- }
- }
kuangbin带我飞QAQ DLX之一脸懵逼的更多相关文章
- kuangbin带我飞QAQ 线段树
1. HDU1166 裸线段树点修改 #include <iostream> #include <string.h> #include <cstdio> #incl ...
- kuangbin带我飞QAQ 并查集
1. POJ 2236 给出N个点,一开始图是空白的,两个操作,一个是增加一个点(给出坐标),一个是查询两个点间是否相通,当两点间的距离小于D或者两点通过其他点间接相连时说这两个点相通.并查集维护,每 ...
- kuangbin带我飞QAQ 最短路
1. poj 1502 Mathches Game 裸最短路 #include <iostream> #include <string.h> #include <cstd ...
- 一脸懵逼学习Hadoop中的序列化机制——流量求和统计MapReduce的程序开发案例——流量求和统计排序
一:序列化概念 序列化(Serialization)是指把结构化对象转化为字节流.反序列化(Deserialization)是序列化的逆过程.即把字节流转回结构化对象.Java序列化(java.io. ...
- Python里面这些点,据说80%的新手都会一脸懵逼
Python里面这些点,据说80%的新手都会一脸懵逼 菜鸟Python 关注 2018.10.10 12:51 字数 1833 阅读 123评论 0喜欢 10 Python虽然语法简单,通俗易懂,但是 ...
- 腾讯一面!说说ArrayList的遍历foreach与iterator时remove的区别,我一脸懵逼
本文基于JDK-8u261源码分析 1 简介 ArrayList作为最基础的集合类,其底层是使用一个动态数组来实现的,这里"动态"的意思是可以动态扩容(虽然ArrayList可 ...
- 一脸懵逼学习基于CentOs的Hadoop集群安装与配置
1:Hadoop分布式计算平台是由Apache软件基金会开发的一个开源分布式计算平台.以Hadoop分布式文件系统(HDFS)和MapReduce(Google MapReduce的开源实现)为核心的 ...
- 一脸懵逼学习Storm---(一个开源的分布式实时计算系统)
Storm的官方网址:http://storm.apache.org/index.html 1:什么是Storm? Storm是一个开源的分布式实时计算系统,可以简单.可靠的处理大量的数据流.被称作“ ...
- Java中线程同步锁和互斥锁有啥区别?看完你还是一脸懵逼?
首先不要钻概念牛角尖,这样没意义. 也许java语法层面包装成了sycnchronized或者明确的XXXLock,但是底层都是一样的.无非就是哪种写起来方便而已. 锁就是锁而已,避免多个线程对同一个 ...
随机推荐
- 用星星画菱形--Java
用星星画菱形 public class Hello{ public static void main(String[] args) { char star = '\u2605'; System.out ...
- JS规则 编程练习 考考大家的数学,计算以下计算公式的结果。然后在浏览器中运行一下,看看结果是否跟你的结果一致。
编程练习 考考大家的数学,计算以下计算公式的结果.然后在浏览器中运行一下,看看结果是否跟你的结果一致. 任务 第一步: 在 ? 处填写你的答案. 第二步: 填写完成后,运行一下,看看是不是跟你填写的 ...
- Luogu P3033 [USACO11NOV]牛的障碍Cow Steeplechase(二分图匹配)
P3033 [USACO11NOV]牛的障碍Cow Steeplechase 题意 题目描述 --+------- -----+----- ---+--- | | | | --+-----+--+- ...
- Python全栈开发:css引入方式
css的四种引入方式: 1.行内式 行内式是在标记的style属性中设定CSS样式.这种方式没有体现出CSS的优势,不推荐使用. <p style="color: red;backgr ...
- [symonfy] An error occurred when executing the "'cache:clear --no-warmup'"
Symfony Version: 3.4.* 当运行 composer update 会出现 [RuntimeException] An error occurred when executing t ...
- A*算法——第K短路
例题 JZOJ senior 1163第K短路 题目描述 Bessie 来到一个小农场,有时她想回老家看看她的一位好友.她不想太早地回到老家,因为她喜欢途中的美丽风景.她决定选择K短路径,而不是最短路 ...
- Zuul上传文件
对于1M以内的文件上传,无需任何处理,大文件10M以上需要为上传路径添加/zuul前缀,也可使用zuul.servlet-path自定义前缀 如果Zuul使用了Ribbon做负载均衡,那么对于超大的文 ...
- iframe跨域数据传递
项目中需要和其他单位合作开发,方案采用iframe嵌入页面,开发过程中设计到了跨域数据的传递,初步方案决定使用html5 API postMessage进行iframe跨域数据传递: 域名A下的页面 ...
- Android之FrameLayout帧布局
1.简介 这个布局直接在屏幕上开辟出一块空白的区域,当我们往里面添加控件的时候,会默认把他们放到这块区域的左上角; 帧布局的大小由控件中最大的子控件决定,如果控件的大小一样大的话,那么同一时刻就只能看 ...
- 05_springmvc参数绑定
一.参数绑定的过程 从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到controller方法的形参上.springmvc中,接收页面提交的数据是通过方法形参来接收.而不 ...