解决这类问题的大体思路:
1)判断所有的情况数,作为列
2)判断所有的条件数,作为行
3)判断每一行满足哪些条件,可以插入1
4)判断是精确覆盖还是重复覆盖
5)注意输入输出
精确覆盖
struct DLX
{
int n,m;///行列的规模
int u[maxnode],d[maxnode],l[maxnode],r[maxnode];///结点四个方向的指针
int col[maxnode],row[maxnode];///结点的行列指针
int h[maxn],s[maxn];
///h[]行首结点(额外的行结点),s[]每一列的个数
bool visit[maxn];///v[]是H()函数的标记数组
int ansed,ans[maxn],siz;///答案的个数,答案,总结点数
void ini(int _n,int _m)///初始化
{
n=_n,m=_m;///规模
for(int i=1;i<=m;i++)///第1->m个结点作为列首节点
{
u[i]=i;///上下指针都指向自己
d[i]=i;
l[i]=i-1;///左右指针相连
r[i]=i+1;
col[i]=i;///列首节点的列指针指向本列
row[i]=0;///列首节点的行指针为第0行
}
///第0个结点(表头head)左指针指向node1,右指针指向nodem
///第m个结点右指针指向head,使得行首结点首尾相接
l[0]=m,r[0]=1;
r[m]=0;
siz=m;
clclow(h);///列首结点初始化为-1,表明该行全为0,没有指向哪个为1的结点
clc(ans);
ansed=0;///答案的数量为0
}
void Link(int R,int c)
{
siz++;///结点数+1
///接下来的操作是在Node_c和Node_c->down之间插入一个结点
///该列从上到下的行号不一定是从小到大的,但是插入的复杂度为O(1)
u[siz]=c;///插入结点的up指针指向c
d[siz]=d[c];///插入结点的down指针指向c->down
u[d[c]]=siz;///结点c->down的up指针指向插入结点
d[c]=siz;///列首结点c的down指针指向插入结点
row[siz]=R,col[siz]=c;///设置行标和列标
if(h[R]<0)///第r行还没有元素
{
h[R]=siz;///第r行的行指针指向插入结点
r[siz]=l[siz]=siz;///插入的结点的左右指针都指向自己
}