很多问题(如求解数独等)都可以转化成求解精确覆盖问题,如果能有一个方便的代码求解这个问题是极好的。
于是伟大的前辈们就发明了X算法,利用十字循环链表(dancing link)求解这个问题。
https://blog.csdn.net/whereisherofrom/article/details/79220897
https://www.cnblogs.com/grenet/p/3145800.html
这两篇博客很好的阐述了X算法的算法思想。
可惜两篇的代码,一个是我不会的语言,一个虽然是C++的代码但是偏向工程化,感觉不是很利于快速理解并实现这个算法,所以这里贴一个C++的简单实现代码。
X算法的核心思想是利用dancing link进行暴力搜索,再回溯。
题目对应洛谷P4929
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define lowbit(x) ((x)&(-(x)))
#define mid ((l+r)>>1)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define fors(i, a, b) for(int i = (a); i < (b); ++i)
using namespace std;
const int maxn = 555;
struct node{
int x, y;
int l, r, u, d;
}e[maxn*maxn];
int head, col[maxn], row[maxn], tot = 0, sz[maxn];
int a[maxn][maxn];
void add(int i, int j){
++tot;//e[tot]代表新结点
sz[j]++;//第j列的点数+1
e[tot] = (node){
i, j, e[row[i]].l, row[i], e[col[j]].u, col[j]};//四个方向
e[e[tot].u].d = tot;//tot上面的点 的 下面的点 变成tot
e[e[tot].d].u = tot;//tot下面的点 的 上面的点 变成tot
e[e[tot].l].r = tot;//tot左面的点 的 右面的点 变成tot
e[e[tot].r].l = tot;//tot右面的点 的 左面的点 变成tot
return;
}