DLX 舞蹈链 精确覆盖 与 重复覆盖
2013-08-12 00:35
357 查看
精确覆盖问题:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1
还有重复覆盖问题
dancing links 是 一种数据结构,用来优化搜索,不算是一种算法。(双向循环十字链表)
参阅了白书训练指南上的模版,目前只有精确覆盖,等再补上重复覆盖
DLX 重复覆盖 template
做了6个题:poj2074 poj3076 前者是9阶数独,后者是16阶数独,以16阶为例,把问题转化为矩阵,总共有16*16*4列,(行、列、小宫格、每个位置)。有16*16*16行。
hust1017 直接给出了精确覆盖问题的定义和模型。不用建模了,直接把输入建成矩阵即可。
zoj3209 矩阵覆盖,行数就是矩阵数,列数为要覆盖的大矩阵的格子数目(化为格子,输入的小矩阵也化为格子后一列就可以出来了)
上面都是精确覆盖,白书训练指南上的模版用的很舒心。
然后我想重复覆盖把这个模版改一改就好吧,结果
FZU 1686 这个题,用改出来的模版死活不过,一直超时,我觉着没啥问题了还是不过。直接去找了另外的模版。另外的题都用了
这题是告诉n*m的格子上有许多1(怪物),然后每次可以消灭(连续的)n1*m1格子内的怪物,问最少几次把所有怪物消灭掉,枚举所有的攻击方案,为行数,列数为1的个数
hdu2295 给定n个城市,m个地点可以建造雷达,最多建k个雷达,问雷达的最小覆盖半径为多少。二分枚举覆盖半径,用重复覆盖判定可否选k个以内的雷达覆盖完所有的城市。行数即为雷达个数,列为城市个数,1为每个雷达可以覆盖到的城市的。这个题目我用的上面的重复覆盖的模版,先把答案求出来然后在判定结果,结果一直超时+wa,之后改为直接在dance的时候限制搜索深度为k就AC了。错了好多次,中间hdu坏了2次,好无奈。。。。
还有重复覆盖问题
dancing links 是 一种数据结构,用来优化搜索,不算是一种算法。(双向循环十字链表)
参阅了白书训练指南上的模版,目前只有精确覆盖,等再补上重复覆盖
const int maxn=360000; const int maxc=500; const int maxr=500; const int inf=0x3f3f3f3f; int L[maxn], R[maxn], D[maxn], U[maxn], C[maxn]; int S[maxc], H[maxr], size; ///不需要S域 void Link(int r, int c) { S[c]++; C[size]=c; U[size]=U[c]; D[U[c]]=size; D[size]=c; U[c]=size; if(H[r]==-1) H[r]=L[size]=R[size]=size; else { L[size]=L[H[r]]; R[L[H[r]]]=size; R[size]=H[r]; L[H[r]]=size; } size++; } void remove(int c){ for (int i=D[c]; i!=c; i=D[i]) L[R[i]]=L[i], R[L[i]]=R[i]; } void resume(int c){ for (int i=U[c]; i!=c; i=U[i]) L[R[i]]=R[L[i]]=i; } int h(){///用精确覆盖去估算剪枝 int ret=0; bool vis[maxc]; memset (vis, false, sizeof(vis)); for (int i=R[0]; i; i=R[i]) { if(vis[i])continue; ret++; vis[i]=true; for (int j=D[i]; j!=i; j=D[j]) for (int k=R[j]; k!=j; k=R[k]) vis[C[k]]=true; } return ret; } int ans; void Dance(int k){ //根据具体问题选择限制搜索深度或直接求解。 if(k+h()>=ans) return; if(!R[0]){ if(k<ans)ans=k; return; } int c=R[0]; for (int i=R[0]; i; i=R[i]) if(S[i]<S[c])c=i; for (int i=D[c]; i!=c; i=D[i]){ remove(i); for (int j=R[i]; j!=i; j=R[j]) remove(j); Dance(k+1); for (int j=L[i]; j!=i; j=L[j]) resume(j); resume(i); } return ; } void initL(int x){///col is 1~x,row start from 1 for (int i=0; i<=x; ++i){ S[i]=0; D[i]=U[i]=i; L[i+1]=i; R[i]=i+1; }///对列表头初始化 R[x]=0; size=x+1;///真正的元素从m+1开始 memset (H, -1, sizeof(H)); ///mark每个位置的名字 }
DLX 重复覆盖 template
做了6个题:poj2074 poj3076 前者是9阶数独,后者是16阶数独,以16阶为例,把问题转化为矩阵,总共有16*16*4列,(行、列、小宫格、每个位置)。有16*16*16行。
hust1017 直接给出了精确覆盖问题的定义和模型。不用建模了,直接把输入建成矩阵即可。
zoj3209 矩阵覆盖,行数就是矩阵数,列数为要覆盖的大矩阵的格子数目(化为格子,输入的小矩阵也化为格子后一列就可以出来了)
上面都是精确覆盖,白书训练指南上的模版用的很舒心。
然后我想重复覆盖把这个模版改一改就好吧,结果
FZU 1686 这个题,用改出来的模版死活不过,一直超时,我觉着没啥问题了还是不过。直接去找了另外的模版。另外的题都用了
这题是告诉n*m的格子上有许多1(怪物),然后每次可以消灭(连续的)n1*m1格子内的怪物,问最少几次把所有怪物消灭掉,枚举所有的攻击方案,为行数,列数为1的个数
hdu2295 给定n个城市,m个地点可以建造雷达,最多建k个雷达,问雷达的最小覆盖半径为多少。二分枚举覆盖半径,用重复覆盖判定可否选k个以内的雷达覆盖完所有的城市。行数即为雷达个数,列为城市个数,1为每个雷达可以覆盖到的城市的。这个题目我用的上面的重复覆盖的模版,先把答案求出来然后在判定结果,结果一直超时+wa,之后改为直接在dance的时候限制搜索深度为k就AC了。错了好多次,中间hdu坏了2次,好无奈。。。。
相关文章推荐
- DLX 舞蹈链 精确覆盖+可重复覆盖
- DLX精确覆盖与重复覆盖模板题
- DLX (精确区间覆盖,重复区间覆盖)(模板)
- SPOJ 1771&&DLX精确覆盖,重复覆盖
- dancing link 精确覆盖 重复覆盖 (DLX)
- dancing link 精确覆盖 重复覆盖 (DLX)
- (模板)dlx 精确覆盖和重复覆盖
- DLX模板之精确覆盖和重复覆盖
- HDU 3957 Street Fighter (最小支配集 DLX 重复覆盖+精确覆盖 )
- HDU 3957 Street Fighter(搜索、DLX、重复覆盖+精确覆盖)
- hdu 3957 Street Fighter 重复覆盖+精确覆盖 DLX
- 最新版dlx模板(精确覆盖+重复覆盖)
- 【转】DLX 精确覆盖 重复覆盖
- DLX 精确覆盖 重复覆盖
- dlx 精确覆盖
- hdu3957Street Fighter(DLX重复覆盖)
- ZOJ 3290 Treasure Map(DLX+精确覆盖)
- ZOJ Treasure Map DLX 精确覆盖
- POJ 1084 Square Destroyer (重复覆盖,DLX)
- [DLX重复覆盖] hdu 3529 Bomberman - Just Search!