HDU 3957 Street Fighter(搜索、DLX、重复覆盖+精确覆盖)
很久以前就看到的一个经典题,一直没做,今天拿来练手。街霸
给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、重复覆盖+精确覆盖)的更多相关文章
- HDU 3957 Street Fighter (最小支配集 DLX 重复覆盖+精确覆盖 )
DLX经典题型,被虐惨了…… 建一个2*N行3*N列的矩阵,行代表选择,列代表约束.前2*N列代表每个人的哪种状态,后N列保证每个人至多选一次. 显然对手可以被战胜多次(重复覆盖),每个角色至多选择一 ...
- DLX 舞蹈链 精确覆盖 与 重复覆盖
精确覆盖问题:给定一个由0-1组成的矩阵,是否能找到一个行的集合,使得集合中每一列都恰好包含一个1 还有重复覆盖问题 dancing links 是 一种数据结构,用来优化搜索,不算是一种算法.(双向 ...
- 【HDOJ】3957 Street Fighter
一定要注意审题啊,题目说的是选出做少的英雄打败其余处在任何模式下的英雄.共有Sigma(num of model)个方案,每个方案有Sigma(num of model)+n个决策.挺不错的一道精确覆 ...
- zoj - 3209 - Treasure Map(精确覆盖DLX)
题意:一个 n x m 的矩形(1 <= n, m <= 30),现给出这个矩形中 p 个(1 <= p <= 500)子矩形的左下角与右下角坐标,问最少用多少个子矩形能够恰好 ...
- hdu 1426 Sudoku Killer ( Dancing Link 精确覆盖 )
利用 Dancing Link 来解数独 详细的能够看 lrj 的训练指南 和 < Dancing Links 在搜索中的应用 >这篇论文 Dancing Link 来求解数独 , ...
- HDU 3111 Sudoku ( Dancing Links 精确覆盖模型 )
推荐两篇学DLX的博文: http://bbs.9ria.com/thread-130295-1-1.html(这篇对DLX的工作过程演示的很详细) http://yzmduncan.iteye.co ...
- HDU 5046 Airport【DLX重复覆盖】
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5046 题意: 给定n个城市的坐标,要在城市中建k个飞机场,使城市距离最近的飞机场的最长距离最小,求这 ...
- HDU 2295.Radar (DLX重复覆盖)
2分答案+DLX判断可行 不使用的估计函数的可重复覆盖的搜索树将十分庞大 #include <iostream> #include <cstring> #include < ...
- [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 ...
随机推荐
- 理解button标签的默认行为
button标签的作用和它的名字一样,在绝大多数场合当做按钮来使用. 很多人在使用button按钮的时候出现过这样或者那样的问题,比如:自动提交表单.一次提交表单多次submit行为,有的浏览器下点击 ...
- 密码学初级教程(一)基本概念及DES加密算法
密码技术在网络通信中广泛使用,本节是初步接触密码学技术的笔记. 第1章 加密-解密 破译 明文-密文 密钥 密码算法 对称密码-公钥密码(非对称密码) 单向散列函数-散列值 消息认证码 数字签名 伪随 ...
- WCF--安全小见解...
由于WCF写的服务需要Ajax来进行调用(这个配置过程也是一个比较咕~~(╯﹏╰)b的经历...), 所以调用的过程都是前台可以看到的,不加点安全措施上去,真的像是一个裸奔在互联网上的接口... 反正 ...
- VTK初学一,a Mesh from vtkImageData
#ifndef INITIAL_OPENGL #define INITIAL_OPENGL #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRend ...
- 基于iSCSI的SQL Server 2012群集测试(四)--模拟群集故障转移
6.模拟群集故障转移 6.1 模拟手动故障转移(1+1) 模拟手动故障转移的目的有以下几点: 测试群集是否能正常故障转移 测试修改端口是否能同步到备节点 测试禁用full-text和Browser服务 ...
- 基于SSL协议的双向认证 - SSL协议 [1]
1 概要说明 在互联网通信方式中,目前用的最广泛的是HTTPS配合SSL和数字证书来保证传输和认证安全了. 2 详细介绍 2.1 HTTPS HTTPS全称:Hypertext Transf ...
- iOS开发——UI进阶篇(四)tableView的全局刷新,局部刷新,左滑操作,左滑出现更多按钮,进入编辑模式,批量删除,自定义批量删除
首先创建项目,在storyboard如下布局控件,设置好约束 然后创建cell模型类XMGWineCell数据模型类XMGWine创建UITableView,设置数据源协议,实现数据源方法懒加载数据这 ...
- BZOJ3223——Tyvj 1729 文艺平衡树
1.题目大意:维护序列,只有区间翻转这个操作 2.分析:splay的经典操作就是实现区间翻转,就是在splay中有一个标记,表示这个区间被翻转了 然后就是记得各种的操作访问某个点时,记得下传,顺便交换 ...
- js计算24点
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 小技巧-a标签去除蓝圈
可以看到,蓝色的边框破坏了页面的整体美感,很多时候我们都是不需要的.通过设置相应的css可以去除点击过后的蓝色边框. map area { outline: none; } 效果如图,点击过后厌人的蓝 ...