hdu 3957 Street Fighter 重复覆盖于+精确覆盖 DancingLink
2015-07-26 13:03
393 查看
Street Fighter
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1257 Accepted Submission(s): 472
Problem Description
Street Fighter is a popular Fighting game. In the game, you could choose many roles to fight.
Each role has some models, in different model the role has different super skill. Such as Ryu, he has two model -- "Metsu Hadoken" and "Metsu Shoryuken". In "Metsu Hadoken" model, Ryu could beat Chun-Li easyly and in "Metsu Shoryuken" he could beat Ken.
Giving the information of which role in which model could beat which role in which model. Your task is choosing minimum roles in certain model to beat other roles in any model.(each role could only be chosen once)
Input
The first line is a number T(1<=T<=30), represents the number of case. The next T blocks follow each indicates a case.
The first line of each case contains a integers N(2<=N<=25), indication the number of roles. (roles numbered from 0 to N - 1).
Then N blocks follow, each block contain the information of a role.
The first of each block contains a integer M(1<=M<=2), indication the number of model of this role.(models numbered from 0 to M - 1)
Then M lines follow, each line contain a number K(1<=K<=10), then K pairs integers(role id and model id) follow, indicating the current role in this model could beat that role in such model.
Output
For each case, output the number of case and the minimum roles have to choose to reach the goal.(as shown in the sample output)
Sample Input
2 2 2 1 1 0 1 1 1 2 1 0 0 1 0 1 4 2 2 1 0 1 1 1 2 0 2 2 3 0 0 1 1 2 0 2 2 0 0 0 1 1 1 0 2 2 2 0 2 1 1 1 0
Sample Output
Case 1: 2 Case 2: 2 Hint In the first sample, you must select all of roles, because one role couldn't beat the other role in any model. In the second sample, you can select role 0 with its model 0, and role 3 with its model 0, then role 1 and role 2 will to be defeated no matter which model they use.
Author
NotOnlySuccess
Source
2011 Alibaba Programming Contest
题意:
有N个英雄,最多有两个状态,每个状态的英雄都能打败一些其他状态的英雄。问,至少选出几个英雄就能打败剩下的英雄的所有状态。
做法:
容易想到的是选出一些状态的英雄打败其他所有英雄,可以用重复覆盖的方法建模型。但是一个英雄只能选一个状态,所以不能是有限制的选择行的。因此还要添加限制条件。同一种英雄的不同状态,设置一个列,如果该列的对应的这个英雄的状态的行上为1.除了在每个状态的英雄能打败的状态的英雄上设置1外,一个英雄的状态能打败这个英雄的其他状态。然后搜索的时候 不对限制列的进行f()函数的判断,优化的时候也不在这些限制的列上选择。只有在选了一行后,才处理限制列,把对应的其他行给删除掉。
#include<iostream> #include<cstdio> #include<cstring> #include<math.h> #include<algorithm> #define maxn 100 #define maxm 1000 using namespace std; //十字链表指针(4) int up[maxm],down[maxm],lef[maxm],righ[maxm]; //行指针,记录在该列为1的行数,覆盖矩阵,行属性,列属性 int head[maxn],sum[maxn],row[maxm],colume[maxm]; bool v[maxn]; //行数,列数,选取行数上线,矩阵点编号 int maxmum,size; //初始化r行,c列 void prepare(int r,int c){ for(int i=0;i<=c;++i){ sum[i]=0; up[i]=down[i]=i; lef[i+1]=i; righ[i]=i+1; } righ[c]=0; size = c; memset(head,-1,sizeof(head)); } //移除某列 void remove(int c){ for(int i = down[c];i != c;i = down[i]) lef[righ[i]]=lef[i],righ[lef[i]]=righ[i]; } //插入某列 void resume(int c){ for(int i=up[c];i!=c;i=up[i]) lef[righ[i]]=righ[lef[i]]=i; } //删除列及其相应的行 void remove1(int c){ int i,j; lef[righ[c]] = lef[c]; righ[lef[c]] = righ[c]; for(i = down[c]; i != c; i = down[i]){ for(j = righ[i]; j != i; j = righ[j]){ up[down[j]] = up[j]; down[up[j]] = down[j]; sum[colume[j]]--; } } } //恢复列及其相应的行 void resume1(int c){ int i,j; righ[lef[c]] = c; lef[righ[c]] = c; for(i = down[c]; i != c; i = down[i]){ for(j = righ[i]; j != i; j = righ[j]){ up[down[j]] = j; down[up[j]] = j; sum[colume[j]]++; } } } int flag; //代价函数 int f(){ int i,j,c,ret=0; for(c = righ[0];c;c = righ[c])v[c]=1; for(c = righ[0];c;c = righ[c]) if(v[c] && c <= flag) for(++ret,v[c]=0,i=down[c];i!=c;i=down[i]){ for(j=righ[i];j!=i;j=righ[j])v[colume[j]]=0; } return ret; } //执行第k层 bool Dance(int k){ if(k+f()>= maxmum)return 0; //righ[0]=0表示覆盖完毕 if(!righ[0] || righ[0] > flag) { //cout<<k<<" k"<<endl; maxmum = k; return 1; } int i,j,c,tmp=maxm; for(i=righ[0];i <= flag;i=righ[i]) if(sum[i]<tmp)tmp=sum[c=i]; for(i=down[c];i!=c;i=down[i]){ remove(i); for(j=righ[i];j!=i;j=righ[j]) if(colume[j] <= flag) remove(j); for(j=righ[i];j!=i;j=righ[j]) if(colume[j] > flag) remove1(colume[j]); Dance(k+1); for(j=lef[i];j!=i;j=lef[j]) if(colume[j] > flag) resume1(colume[j]); for(j=lef[i];j!=i;j=lef[j]) if(colume[j] <= flag) resume(j); resume(i); } return 0; } //插入r行c列 void Link(int r,int c){ ++sum[colume[++size] = c]; down[size] = down[c]; up[down[c]] = size; up[size] = c; down[c] = size; row[size] = r; if(head[r] < 0)head[r] = lef[size] = righ[size] = size; else{ righ[size] = righ[head[r]]; lef[righ[head[r]]] = size; lef[size] = head[r]; righ[head[r]] = size; } } int ma[100][200]; int ty[50]; int su[50]; int kil[50]; int rol[50][50][2]; int main(){ int t,n,m; scanf("%d",&t); for(int tt = 1; tt<= t;tt++){ scanf("%d",&n); memset(ma,0,sizeof(ma)); int cnt = 0; for(int i = 0;i < n; i++){ scanf("%d",&ty[i]); for(int l = 0;l < ty[i]; l++){ scanf("%d",&kil[cnt]); for(int j = 0;j < kil[cnt];j++) scanf("%d%d",&rol[cnt][j][0],&rol[cnt][j][1]); cnt++; } } su[0] = ty[0]; for(int i = 1; i < n; i++) su[i] = su[i-1] + ty[i]; for(int i = 0;i < cnt; i++){ for(int j = 0;j < kil[i];j++){ int u = rol[i][j][0]; u = su[u] - ty[u] + rol[i][j][1]; ma[i][u] = 1; } } flag = cnt ; for(int i = 0;i < n; i++){ for(int j = 0;j < ty[i]; j++){ int u = su[i] - ty[i] + j; ma[u][cnt+i] = 1; for(int k = 0;k < ty[i]; k++){ int vv = su[i] - ty[i] + k; ma[u][vv] = 1; } } } prepare(cnt ,cnt + n); for(int i = 0;i < cnt; i++){ for(int j = 0;j < cnt +n; j++){ if(ma[i][j]) Link(i+1,j+1); } } maxmum = n; int x = Dance(0); printf("Case %d: %d\n",tt,maxmum); } return 0; } /* 剪枝说明 1,选取一列未覆盖的列,选取在该列上为1的所有行,把这些行对应的所有列都覆盖 2,重复1直到所有列被覆盖得到f(),可知最少需要f()行才能覆盖所有列 输出结果:在Dance中如果返回1则记录该点 */
相关文章推荐
- test项目从零开始
- Fedora20上Xen的安装与部署
- android.app.PendingIntent
- 求2~2000的所有素数.有足够的内存,要求尽量快
- Leetcode 20 Valid Parentheses
- NativeXml (1):下载、安装、测试
- html之marquee详解
- 并行聚合操作
- Active Directory 禁用客户端缓存登陆
- 代码大全1-3章笔记
- 数据库性能指标说明
- 2015--智慧家庭(服务器)
- A - 敌兵布阵 - hdu 1166
- Java关键字this、super使用总结
- [LeetCode]Single Number
- jdk 安装
- WebGL框架 -- three.js
- Unity中的摄像机camera的depth属性与Render Queue的区别
- 插入排序之表插入排序
- Swift学习笔记(二)——常量与变量