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 ...
随机推荐
- Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法
Easyui中使用jquery或js动态添加元素时出现的样式失效的解决方法 2014-03-27 11:44:46| 分类: Easy UI|举报|字号 订阅 可以使用$.parser.pa ...
- WCF--提示:异常消息为“传入消息的消息格式不应为“Raw”。此操作的消息格式应为 'Xml', 'Json'。
Ajax调用WCF服务... 本来用 // $.getJSON("http://localhost:16625/Service1.svc/Article_GetInfo", { } ...
- 如何催促Apple进行App审核
为什么提交给 App Store 的应用进入"审核(In Review)"状态后, 仍然可能会等待好多天的时间 ? 不过你也可以通过催促Apple进行App审核来缩短这个时间.以下 ...
- dede自定义表单增加添加时间怎么弄
我们在用dedecms添加自定义表单时有时想要设置一个用户提交的时间,方便查询,比如我们的客服人员查询昨天晚上下班后有哪些订单是刚生成的,比较好查看,如下图所示.那么,dedecms自定义表单增加添加 ...
- 2012多校3.A(用O(log(n))判断b^k % a == 0)
Arcane Numbers 1 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Su ...
- Jetty安装
下载jetty http://www.eclipse.org/jetty/ 看好jdk 版本 安装 解压压缩包到指定目录,且将其目录路径定义为${JETTY_HOME} 进入${JETTY_HOME ...
- 第三天 moyax
struct Blog { static let BaseURL = NSURL(string: "http://192.168.1.103/blog")! } extension ...
- springMVC之国际化
1.工程结构 2.jar包 3.配置文件spring-config.xml,springMVC配置文件 <?xml version="1.0" encoding=" ...
- 【转】php 下载保存文件保存到本地的两种实现方法
来源:http://www.jb51.net/article/40485.htm 第一种: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php function d ...
- (二)js下拉菜单
默认的select标签比较难看,UI比较漂亮,如果想要实现UI上的下拉样式,好像必须用js写select,从网上拷贝而且修改了一个下拉框,为了方便以后引用所以记录下来. /* diy_select * ...