Dancing Links,跳舞链,是一种数据结构以及配套的算法,用于解决精确覆盖问题与重复覆盖问题。具体讲解博客链接:
https://www.cnblogs.com/grenet/p/3145800.html
https://www.cnblogs.com/wujiechao/p/5767124.html
ZOJ3029 Treasure Map:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
typedef long long ll;
using namespace std;
const int MAXN = 500010;
const int MAX = 510;
const int MAXM = 1010;
struct DancingLinks
{
int n, m;
int U[MAXN], D[MAXN], L[MAXN], R[MAXN];
int row[MAXN], col[MAXN];
int rowHead[MAX], nodeNumOfCol[MAXM];
int ansd, nodeNum;
void init(int _n, int _m)
{
n = _n;
m = _m;
for(int i = 0; i <= m; i++)
{
nodeNumOfCol[i] = 0;
U[i] = D[i] = i;
L[i] = i - 1;
R[i] = i + 1;
}
R[m] = 0; L[0] = m;
nodeNum = m;
for(int i = 1; i <= n; i++)
rowHead[i] = -1;
}
void push(int r, int c)
{
++nodeNumOfCol[col[++nodeNum] = c];
row[nodeNum] = r;
D[nodeNum] = D[c];
U[D[c]] = nodeNum;
U[nodeNum] = c;
D[c] = nodeNum;
if(rowHead[r] < 0)
rowHead[r] = R[nodeNum] = L[nodeNum] = nodeNum;
else
{
R[nodeNum] = R[rowHead[r]];
L[R[rowHead[r]]] = nodeNum;
L[nodeNum] = rowHead[r];
R[rowHead[r]] = nodeNum;
}
}
void del(int c)//删除第c列及其节点所在的行
{
L[R[c]] = L[c]; R[L[c]] = R[c];
for(int i = D[c]; i != c; i = D[i])
for(int j = R[i]; j != i; j = R[j])
{
U[D[j]] = U[j];
D[U[j]] = D[j];
--nodeNumOfCol[col[j]];
}
}
void reback(int c)//恢复第c列及其节点所在行
{
for(int i = U[c]; i != c; i = U[i])
for(int j = L[i]; j != i; j = L[j])
++nodeNumOfCol[col[U[D[j]] = D[U[j]] = j]];
L[R[c]] = R[L[c]] = c;
}
void Dance(int d)
{
if(ansd != -1 && ansd <= d) return;
if(R[0] == 0)
{
if(ansd == -1)
ansd = d;
else if(d < ansd)
ansd = d;
return;
}
int c = R[0];
for(int i = R[0]; i != 0; i = R[i])
if(nodeNumOfCol[i] < nodeNumOfCol[c])
c = i;
del(c);
for(int i = D[c]; i != c; i = D[i])
{
for(int j = R[i]; j != i; j = R[j])
del(col[j]);
Dance(d+1);
for(int j = L[i]; j != i; j = L[j])
reback(col[j]);
}
reback(c);
}
};
DancingLinks dlx;
int main()
{
int t;
int n, m, p;
scanf("%d", &t);
while(t--)
{
scanf("%d %d %d", &n, &m, &p);
dlx.init(p, n*m);
int x1, y1, x2, y2;
for(int e = 1; e <= p; e++)
{
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
for(int i = x1+1; i <= x2; i++)
for(int j = y1+1; j <= y2; j++)
dlx.push(e, j+(i-1)*m);
}
dlx.ansd = -1;
dlx.Dance(0);
printf("%d\n", dlx.ansd);
}
return 0;
}
HDU2295 Radar:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxnode = 3000;
const int MaxM = 55;
const int MaxN = 55;
struct DLX
{
int n, m, nodeNum;
int U[maxnode], D[maxnode], R[maxnode], L[maxnode];
int Row[maxnode], Col[maxnode];
int H[MaxN], S[MaxN];
int ands, ans[MaxN];
int K;
void init(int _n, int _m)
{
n = _n;
m = _m;
for(int i = 0; i <= m; i++)
{
S[i] = 0;
U[i] = D[i] = i;
L[i] = i-1;
R[i] = i+1;
}
R[m] = 0; L[0] = m;
nodeNum = m;
for(int i = 1; i <= n; i++)
H[i] = -1;
}
void push(int r, int c)
{
++S[Col[++nodeNum] = c];
Row[nodeNum] = r;
D[nodeNum] = D[c];
U[D[c]] = nodeNum;
U[nodeNum] = c;
D[c] = nodeNum;
if(H[r] < 0) H[r] = L[nodeNum] = R[nodeNum] = nodeNum;
else
{
R[nodeNum] = R[H[r]];
L[R[H[r]]] = nodeNum;
L[nodeNum] = H[r];
R[H[r]] = nodeNum;
}
}
void del(int c)
{
for(int i = D[c]; i != c; i = D[i])
L[R[i]] = L[i], R[L[i]] = R[i];
}
void reback(int c)
{
for(int i = U[c]; i != c; i = U[i])
L[R[i]] = R[L[i]] = i;
}
bool v[maxnode];
int f() //评估函数
{
int ret = 0;
for(int e = R[0]; e != 0; e = R[e]) v[e] = true;
for(int e = R[0]; e != 0; e = R[e])
if(v[e])
{
ret++;
v[e] = false;
for(int i = D[e]; i != e; i = D[i])
for(int j = R[i]; j != i; j = R[j])
v[Col[j]] = false;
}
return ret;
}
bool Dance(int d)
{
if(d + f() > K) return false; //用评估函数剪枝
if(R[0] == 0) return d <= K;
int c = R[0];
for(int i = R[0]; i != 0; i = R[i])
if(S[i] < S[c])
c = i;
for(int i = D[c]; i != c; i = D[i])
{
del(i);
for(int j = R[i]; j != i; j = R[j]) del(j);
if(Dance(d+1)) return true;
for(int j = L[i]; j != i; j = L[j]) reback(j);
reback(i);
}
return false;
}
};
DLX g;
struct point
{
int x, y;
void input()
{
scanf("%d %d", &x, &y);
}
}city[MaxN], Radar[MaxM];
double dis(point a, point b)
{
return
sqrt((double)(a.x-b.x)*(a.x-b.x) + (double)(a.y-b.y)*(a.y-b.y));
}
const double eps = 1e-8;
int main()
{
int t;
int n, m;
int k;
scanf("%d", &t);
while(t--)
{
scanf("%d %d %d", &n, &m, &k);
for(int i = 0; i < n; i++) city[i].input();
for(int i = 0; i < m; i++) Radar[i].input();
g.K = k;
double l = 0, r = 5000;
while(r-l >= eps)
{
double mid = (l+r)/2;
g.init(m, n);
for(int i = 0; i < m; i++)
for(int j = 0; j < n; j++)
if(dis(Radar[i], city[j]) < mid - eps)
g.push(i+1, j+1);
if(g.Dance(0)) r = mid-eps;
else l = mid+eps;
}
printf("%.6f\n", l);
}
return 0;
}
FZU1686 神龙的难题:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
typedef long long ll;
using namespace std;
const int maxnode = 15*15*15*15+100;
const int MaxM = 15*15+10;
const int MaxN = 15*15+10;
const int INF = 0x3f3f3f3f;
struct DLX
{
int n, m, nodeNum;
int U[maxnode], D[maxnode], R[maxnode], L[maxnode];
int Row[maxnode], Col[maxnode];
int H[MaxN]/*每行的头指针*/, S[MaxN]/*每列的节点个数*/;
int ansd;
void init(int _n, int _m)
{
n = _n;
m = _m;
for(int i = 0; i <= m; i++)
{
S[i] = 0;
U[i] = D[i] = i;
L[i] = i-1;
R[i] = i+1;
}
R[m] = 0; L[0] = m;
nodeNum = m;
for(int i = 1; i <= n; i++)
H[i] = -1;
}
void push(int r, int c)
{
++S[Col[++nodeNum] = c];
Row[nodeNum] = r;
D[nodeNum] = D[c];
U[D[c]] = nodeNum;
U[nodeNum] = c;
D[c] = nodeNum;
if(H[r] < 0) H[r] = L[nodeNum] = R[nodeNum] = nodeNum;
else
{
R[nodeNum] = R[H[r]];
L[R[H[r]]] = nodeNum;
L[nodeNum] = H[r];
R[H[r]] = nodeNum;
}
}
void del(int c)
{
for(int i = D[c]; i != c; i = D[i])
L[R[i]] = L[i], R[L[i]] = R[i];
}
void reback(int c)
{
for(int i = U[c]; i != c; i = U[i])
L[R[i]] = R[L[i]] = i;
}
bool v[maxnode];
int f() //评估函数
{
int ret = 0;
for(int e = R[0]; e != 0; e = R[e]) v[e] = true;
for(int e = R[0]; e != 0; e = R[e])
if(v[e])
{
ret++;
v[e] = false;
for(int i = D[e]; i != e; i = D[i])
for(int j = R[i]; j != i; j = R[j])
v[Col[j]] = false;
}
return ret;
}
void Dance(int d)
{
if(d + f() >= ansd) return; //用评估函数剪枝
if(R[0] == 0)
{
if(d < ansd) ansd = d;
return;
}
int c = R[0];
for(int i = R[0]; i != 0; i = R[i])
if(S[i] < S[c])
c = i;
for(int i = D[c]; i != c; i = D[i])
{
del(i);
for(int j = R[i]; j != i; j = R[j]) del(j);
Dance(d+1);
for(int j = L[i]; j != i; j = L[j]) reback(j);
reback(i);
}
}
};
DLX g;
int Map[20][20];
int main()
{
int n, m, n1, m1;
while(~scanf("%d %d", &n, &m))
{
memset(Map, 0, sizeof(Map));
int num, cnt = 0;
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
{
scanf("%d", &num);
if(num == 1) Map[i][j] = (++cnt);
else Map[i][j] = 0;
}
g.init(n*m, cnt);
cnt = 1; //row
scanf("%d %d", &n1, &m1);
for(int i = 0; i < n-n1+1; i++)
for(int j = 0; j < m-m1+1; j++)
{
for(int e = i; e < i+n1; e++)
for(int k = j; k < j+m1; k++)
if(Map[e][k])
g.push(cnt, Map[e][k]);
cnt++;
}
g.ansd = INF;
g.Dance(0);
printf("%d\n", g.ansd);
}
return 0;
}
POJ3074 Sudoku:https://blog.csdn.net/baidu_29410909/article/details/51289650
目前作为模板储存。