這幾天終於鼓起勇氣學了舞蹈鏈這種資料結構,在聯絡的過程中發現一般分為兩種情況
精確覆蓋和重複覆蓋
首先將一下精確覆蓋,顧名思義就是覆蓋全部的元素且只能覆蓋一次
在**實現的方面講即給出的0_1矩陣中找到對應的行號使這些行組成組成的新矩陣每列只有乙個1
模板:#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3fll;
const int maxn=1010;
int l[maxn*100],r[maxn*100],u[maxn*100],d[maxn*100];//節點的上下左右四個方向的鍊錶
int c[maxn*100],h[maxn],cnt[maxn],vis[maxn],ans[maxn],row[maxn*100];//c列h行cnt列煉表中元素個數
int n,m,id,len;
void init()
r[m]=0;id=m+1;
memset(h,-1,sizeof(h));
}void link(int r,int c)
id++;
}void remove(int size)}}
void resume(int size)
}l[r[size]]=size;r[l[size]]=size;
}int dance(int k)
for(int i=r[0];i;i=r[i])
}remove(pos);
for(int i=d[pos];i!=pos;i=d[i])
resume(pos);
return 0;
}int main()
//len代表個數,具體存在ans陣列中
2 就是重複覆蓋,意思也是覆蓋全部元素但可以重複
同上,只不過每列最少1個1
模板:#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3fll;
const int maxn=60;
int l[maxn*maxn],r[maxn*maxn],u[maxn*maxn],d[maxn*maxn];//節點的上下左右四個方向的鍊錶
int c[maxn*maxn],h[maxn],cnt[maxn],vis[maxn];//c列h行cnt列煉表中元素個數
int n,m,id,fans;
vectorg[maxn];
void init()
r[n]=0;id=n+1;
memset(h,-1,sizeof(h));
}void link(int r,int c)
id++;
}void remove(int size)
void resume(int size)
int h()
}return sum;
}void dance(int k)
}int main()
for(int i=1;i<=n;i++)
}fans=n;
dance(0);
printf("%d\n",fans);
}return 0;
}
舞蹈鏈 精確覆蓋,解決數獨問題
首先看看數獨問題 9 9的方格 的規則 1 每個格仔只能填乙個數字 2 每行每個數字只能填一遍 3 每列每個數字只能填一遍 4 每宮每個數字只能填一遍 那現在就是利用這個規則把數獨問題轉換為精確覆蓋問題 可是,直觀上面的規則,發現比較難以轉換為精確覆蓋問題。因此,把上面的表述換個說法 1 每個格仔只...
P4929 模板 舞蹈鏈 DLX
n m 的矩形有 0 1 要求選出若干行使得每一列有且僅有乙個 1 精確覆蓋問題指的是乙個集合 s 和它的若干個子集集合 t 要求選出 t 的乙個子集使得裡面的集合元素剛好覆蓋集合 s dlx 全稱是 dancing link x 其中 dancing link 是指交叉十字迴圈雙向鏈,x 是指暴搜...
HDU 3529 舞蹈鏈之可重複覆蓋
點選開啟鏈結 題意 在點的地方放炸彈,炸彈可以炸到的地方無限遠並且是十字的形式,但是如果炸到 或者 則這個方向停下來,問最少需要多少炸彈同時引爆才可以將所有 炸掉 思路 一道模版舞蹈鏈了,對於建圖我們將所有的 看做列,然後所有的點也就是放炸彈的地方看做行,然後找一下每個點可以炸的 就可以了,建圖後跑...