您的位置:首页 > 其它

hdu3957Street Fighter(DLX重复覆盖)

2013-10-06 15:46 218 查看
题目请戳这里

题目大意:在游戏Street Fighter(街头霸王)中有若干个角色,每个角色有1~2个模式,每个角色在某个模式下可以KO另外某些模式下的某些角色。现在给n个角色和他们的模式以及各自在相应模式下能KO的对手及对手的模式。求最少需要几个角色能KO所有其他角色。

题目分析:重复覆盖问题,DLX解决。因为每个角色有1~2个模式,所以抽象出2*n行和2*n列。直接建图跑DLX即可。

需要注意的问题:

1:每个角色要对自己建边,因为自己不需要KO。

2:有的角色没有model2,所以建图后要把没有列元素的列头删掉(此处wa数次!!)

3:要判重,一个角色只能选一次。

详情请见代码:

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 3000;
int n,num;
bool vis[55];
bool flag[55];
int data[55][55];
int ans;
int h
,s
,u
,d
,l
,r
,row
,col
;
int lim;
int md[26];
void init(int tn)
{
memset(h,0,sizeof(h));
memset(s,0,sizeof(s));
memset(flag,false,sizeof(flag));
for(int i = 0;i <= tn;i ++)
{
u[i] = d[i] = i;
l[i] = (i + tn) % (tn + 1);
r[i] = (i + 1) % (tn + 1);
}
num = tn + 1;
}
void build(int i,int j)
{
if(h[i])
{
r[num] = h[i];
l[num] = l[h[i]];
r[l[num]] = l[r[num]] = num;
}
else
h[i] = l[num] = r[num] = num;
s[j] ++;
u[num] = u[j];
d[num] = j;
d[u[num]] = num;
u[j] = num;
col[num] = j;
row[num] = i;
num ++;
}
void prepare()
{
scanf("%d",&n);
int i,j,m,k,a,b;
init(n + n);
memset(md,0,sizeof(md));
memset(data,0,sizeof(data));
for(i = 0;i < n;i ++)
{
scanf("%d",&md[i]);
data[i<<1|1][i<<1|1] = 1;
for(j = 1;j <= md[i];j ++)
{
scanf("%d",&m);
while(m --)
{
scanf("%d%d",&a,&b);
data[(i<<1)+j][(a<<1)+b+1] = 1;
}
}
if(md[i] == 2)
{
data[i<<1|1][(i<<1)+2] = 1;
data[(i<<1)+2][(i<<1)+2] = 1;
data[(i<<1)+2][i<<1|1] = 1;
}
}
for(i = 2;i <= n + n;i += 2)//!!!!!!!删除没有模式2的列头!!!
if(md[(i>>1)-1] == 1)
r[l[i]] = r[i],l[r[i]] = l[i];
for(i = 1;i <= n + n;i ++)
{
for(j = 1;j <= n + n;j ++)
{
if(data[i][j])
{
build(i,j);
}
}
}
}
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 A()
{
int i,j,k,ret = 0;
memset(vis,false,sizeof(vis));
for(i = r[0];i;i = r[i])
{
if(vis[i] == false)
{
ret ++;
vis[i] = true;
for(j = d[i];j != i;j = d[j])
for(k = r[j];k != j;k = r[k])
vis[col[k]] = true;
}
}
return ret;
}
void dfs(int k)
{
if(k + A() >= ans)
return ;
if(!r[0])
{
ans = min(ans,k);
return ;
}
int i,j,c,mn = N;
for(i = r[0];i;i = r[i])
{
if(s[i] < mn)
{
mn = s[i];
c = i;
}
}
for(i = d[c];i != c;i = d[i])
{
if(flag[(row[i] + 1)>>1] == true)
continue;
remove(i);
flag[(row[i] + 1)>>1] = true;
for(j = r[i];j != i;j = r[j])
remove(j);
dfs(k + 1);
for(j = l[i];j != i;j = l[j])
resume(j);
resume(i);
flag[(row[i] + 1)>>1] = false;
}
}
void dance(int cas)
{
ans = n;
dfs(0);
printf("Case %d: %d\n",cas,ans);
}
int main()
{
int _,cas = 0;
scanf("%d",&_);
while(_ --)
{
prepare();
dance(++cas);
}
return 0;
}
//1937MS	340K
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  搜索