很久以前就看到的一个经典题,一直没做,今天拿来练手。街霸

给n<=25个角色,每个角色有 1 or 2 个版本(可以理解为普通版以及爆发版),每个角色版本可以KO掉若干人。

问最少选多少个角色(每个角色只能选一次),使得可以KO掉其他所有人(包括所有版本)。

典型的DLX。前∑mode[i]列表示被KO的人版本,重复覆盖。后n列表示选了的人,精确覆盖。

即,在精确覆盖满足的前提下,完成重复覆盖,且使所选行最少。

据说这题可以转化成只用一种覆盖,或者是dfs+剪枝。这里就先这样吧。

加了好多注释,方便以后看。

注意的是,dance的时候,要先删除重复覆盖,再删除精确覆盖。。。

2515MS

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <map>
using namespace std; #define MP make_pair
#define ll long long
#define inf 0x3f3f3f3f #define maxr 88
#define maxn (maxr*maxr)
struct DLX{
int m;// amount of column
int m1,m2;// amount of repeat column and exact column
int L[maxn],R[maxn],U[maxn],D[maxn],cnt;
int row[maxn],col[maxn];
int N[maxr],use[maxr],head[maxr];
void init(int _m){// may need modify this function
m = _m;
memset(head,-1,sizeof(head));
memset(N,0,sizeof(N));
for(int i=0;i<=m;++i){
L[i]=i-1,R[i]=i+1;
U[i]=D[i]=i;
row[i]=0,col[i]=i;
}
L[0]=m,R[m]=0;
cnt=m;
best = inf;
}
void exrm(int c){// remove of exact cover, private
L[R[c]]=L[c],R[L[c]]=R[c];
for(int i=D[c];i!=c;i=D[i])
for(int j=R[i];j!=i;j=R[j])
U[D[j]]=U[j],D[U[j]]=D[j],--N[col[j]];
}
void exres(int c){// resume of exact cover, private
for(int i=U[c];i!=c;i=U[i])
for(int j=L[i];j!=i;j=L[j])
U[D[j]]=D[U[j]]=j,++N[col[j]];
L[R[c]]=R[L[c]]=c;
}
void rm(int x){// remove of repeat cover, private
for(int i=D[x];i!=x;i=D[i])
L[R[i]]=L[i],R[L[i]]=R[i];
}
void res(int x){// resume of repeat cover, private
for(int i=D[x];i!=x;i=D[i])
L[R[i]]=R[L[i]]=i;
}
int low(){// private, sometimes need modify this function
int mi=maxr,idx=0;
for(int i=R[0];i<=m1;i=R[i])if(N[i]<mi&&N[i])mi=N[i],idx=i;
return idx;
}
void link(int r,int c){
++N[c],++cnt;
row[cnt]=r,col[cnt]=c;
U[cnt]=U[c],D[cnt]=c;
U[D[cnt]]=D[U[cnt]]=cnt;
if(head[r]==-1)
head[r]=L[cnt]=R[cnt]=cnt;
else {
L[cnt]=L[head[r]];
R[cnt]=head[r];
L[R[cnt]]=R[L[cnt]]=cnt;
}
}
bool del[maxr];
int cost2(){// lower_bound
int ret=0;
memset(del,false,sizeof(del));
for(int c=R[0];c && c<=m1;c=R[c]){
if(!del[c]){
del[c]=true;
ret++;
for(int i=D[c];i!=c;i=D[i])
for(int j=R[i];j!=i;j=R[j])
del[col[j]]=true;
}
}
return ret;
}
int best;
void dance(int dep,int val){// always need modify this function
if(R[0]==0 || R[0]>m1){
best = min(best, val);
return ;
}
int c=low();
if(c==0)return ;
if(dep+cost2()>=best) return ;
for(int i=D[c];i!=c;i=D[i]){
int r=row[i];
use[dep]=i;
rm(i);
for(int j=R[i];j!=i;j=R[j]) if(col[j]<=m1) rm(j);
for(int j=R[i];j!=i;j=R[j]) if(col[j]>m1) exrm(col[j]);
dance(dep+1,val+1);
for(int j=L[i];j!=i;j=L[j]) if(col[j]>m1) exres(col[j]);
for(int j=L[i];j!=i;j=L[j]) if(col[j]<=m1) res(j);
res(i);
}
}
}dlx; int mode[30];
int sum[30];
vector<pair<int,int> >beat[30][2];
int main(){
int t,ca=0;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=0;i<n;++i){
scanf("%d",mode+i);
if(i==0) sum[i] = mode[i];
else sum[i] = sum[i-1]+mode[i];
for(int j=0;j<mode[i];++j){
int k,beatp,beatm;
scanf("%d",&k);
beat[i][j].clear();
for(int kk=0;kk<k;++kk){
scanf("%d%d",&beatp,&beatm);
beat[i][j].push_back(MP(beatp,beatm));
}
}
}
dlx.init(sum[n-1]+n);
dlx.m1 = sum[n-1], dlx.m2 = n;
for(int i=0;i<n;++i){
for(int j=0;j<mode[i];++j){
int row = (i?sum[i-1]:0)+j+1;
dlx.link(row,sum[n-1]+i+1);// exact cover
dlx.link(row,(i?sum[i-1]:0)+1);// repeat cover
if(mode[i]==2) dlx.link(row,(i?sum[i-1]:0)+2);// repeat cover
for(int k=0;k<beat[i][j].size();++k){// repeat cover
pair<int,int>tmp = beat[i][j][k];
int beatp = tmp.first;
int beatm = tmp.second;
int col = (beatp?sum[beatp-1]:0)+beatm+1;
dlx.link(row,col);
}
}
}
dlx.dance(0,0);
printf("Case %d: %d\n",++ca,dlx.best);
}
return 0;
}

HDU 3957 Street Fighter(搜索、DLX、重复覆盖+精确覆盖)的更多相关文章

  1. HDU 3957 Street Fighter (最小支配集 DLX 重复覆盖+精确覆盖 )

    DLX经典题型,被虐惨了…… 建一个2*N行3*N列的矩阵,行代表选择,列代表约束.前2*N列代表每个人的哪种状态,后N列保证每个人至多选一次. 显然对手可以被战胜多次(重复覆盖),每个角色至多选择一 ...

  2. DLX 舞蹈链 精确覆盖 与 重复覆盖

    精确覆盖问题:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 还有重复覆盖问题 dancing links 是 一种数据结构,用来优化搜索,不算是一种算法.(双向 ...

  3. 【HDOJ】3957 Street Fighter

    一定要注意审题啊,题目说的是选出做少的英雄打败其余处在任何模式下的英雄.共有Sigma(num of model)个方案,每个方案有Sigma(num of model)+n个决策.挺不错的一道精确覆 ...

  4. zoj - 3209 - Treasure Map(精确覆盖DLX)

    题意:一个 n x m 的矩形(1 <= n, m <= 30),现给出这个矩形中 p 个(1 <= p <= 500)子矩形的左下角与右下角坐标,问最少用多少个子矩形能够恰好 ...

  5. hdu 1426 Sudoku Killer ( Dancing Link 精确覆盖 )

    利用 Dancing Link 来解数独 详细的能够看    lrj 的训练指南 和 < Dancing Links 在搜索中的应用 >这篇论文 Dancing Link 来求解数独 , ...

  6. HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )

    推荐两篇学DLX的博文: http://bbs.9ria.com/thread-130295-1-1.html(这篇对DLX的工作过程演示的很详细) http://yzmduncan.iteye.co ...

  7. HDU 5046 Airport【DLX重复覆盖】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5046 题意: 给定n个城市的坐标,要在城市中建k个飞机场,使城市距离最近的飞机场的最长距离最小,求这 ...

  8. HDU 2295.Radar (DLX重复覆盖)

    2分答案+DLX判断可行 不使用的估计函数的可重复覆盖的搜索树将十分庞大 #include <iostream> #include <cstring> #include < ...

  9. [ACM] HDU 2295 Radar (二分法+DLX 重复覆盖)

    Radar Problem Description N cities of the Java Kingdom need to be covered by radars for being in a s ...

随机推荐

  1. 使用jQuery的Scrollify插件实现鼠标滚轮或者手势滑动到页面下一节点部分

    有时我们需要做一个单页面介绍产品特性,而单页面内容非常多且页面非常长,为了快速定位到产品特性节点,我们使用js侦听用户滚轮事件,当用户触发滚轮滑动或者使用手势触屏滑动时,即可定位到相应的节点.一款jQ ...

  2. 点击自动显示/隐藏DIV代码。(简单实用)

    注:本文由Colin撰写,版权所有!转载请注明原文地址,谢谢合作! 很多时候我们需要将DIV的信息默认为隐藏状态,只有当用户点击时才显示DIV中包含的提示文字.这类效果在互联网上应用得很多,但实现的方 ...

  3. php补充

    PHP 教程 echo 和 print 之间的差异:echo - 能够输出一个以上的字符串print - 只能输出一个字符串,并始终返回 1提示:echo 比 print 稍快,因为它不返回任何值. ...

  4. Hadoop之Storm安装

    nimbus:主节点,负责分发代码,分配任务(只能有一个)supervisor:从节点,负责执行任务(可以有多个) jdkzookeeper(192.168.1.170/171/172)建议在zook ...

  5. EF初接触01

    自动属性:{get;set} 隐式类型 var, dynamic var:  隐式的类型推断出来,在编译阶段把Var换成对应的实际的类型 所以只应用在编译之间, 在运行阶段是和实际类型意义的 dyna ...

  6. 自定义Listview

    public class MyListView extends ListView { public MyListView(Context context) { super(context); } pu ...

  7. BZOJ2555——SubString

    0.题目很短,就不概括了 给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. ...

  8. POJ3461——Oulipo

    1.题目大意:单字符串匹配问题 2.分析:经典KMP问题 存个模板QAQ #include <cstdio> #include <cstdlib> #include <c ...

  9. css弹性布局

    1.弹性布局是什么 在移动端一种方便的布局方式,打破了之前用浮动,定位的布局,更加灵活. 2.弹性布局的格式 包含父元素和子元素,有对应的属性应用在父元素和子元素达到布局的目的 3.父元素的属性 要开 ...

  10. 关于Promise:你可能不知道的6件事

    FROM ME : 文章介绍了6个Promise的知识点: 1.then() 返回一个 forked Promise(分叉的 Promise):返回的有两种情况: 2.回调函数应该传递结果:在 pro ...