dancing link
dancing link x
DLX又称dancing links X 是一种 解决重复覆盖和精确覆盖的高效算法
精准覆盖:一个全集S有若干个子集S1,S2,……Sn,选取其中若干个子集,使得这些集合中出现了S中每个元素各一次。举个例子:
全集S={1,2,3,4,5,6,7}, 用子集S1={1,2,3},S2={3,4,5,7},S3={4,5,6,7},S4={1,5,6,7},S5={4,5}精确覆盖,结果显然是选取S1和S3。
刚才的例子表示为:
\[\left|\begin{array}{cccc}
S & 1 &2 &3 &4 &5 &6&7\\
S_1&1&1&1&0&0&0&0\\
S_2&0&0&1&1&1&0&1\\
S_3&0&0&0&1&1&1&1\\
S_4&1&0&0&0&1&1&1\\
S_5&0&0&0&1&1&0&0\\
\end{array}\right| \\
\]
\[核心操作:选取一个集合(一行),把~该行~和~该行上有点的列和包含这些列的行删除\\
比如我们删掉了第一行\\
\left|\begin{array}{cccc}
S&4&5&6&7\\
S_3&1&1&1&1\\
S_5&1&1&0&0
\end{array}\right| \\
\]
接下来如果我们选择了S3,显然矩阵为空,我们找到了一组解,但若我们选择了S5则矩阵变为
\[\left|\begin{array}{cccc}
S&6&7
\end{array}\right| \\
\]
矩阵未覆盖完但已经无集合可用,覆盖失败,于是要回溯,于是矩阵又为
\[\left|\begin{array}{cccc}
S&4&5&6&7\\
S_3&1&1&1&1\\
S_5&1&1&0&0
\end{array}\right| \\
\]
int n,m,cnt;//矩阵的长,宽,点的数量
int l[mx],r[mx],u[mx],d[mx],row[mx],col[mx];//每个点的左,右,上下,行,列信息
int h[mx];//每行的头结点
int s[mx];//每列的结点数
int ans,ansk[mx];//需要ans个子集,分别为ansk[]
没码完一会继续咕咕咕