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:要判重,一个角色只能选一次。
详情请见代码:
题目大意:在游戏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
相关文章推荐
- FZU Problem 1686 神龙的难题 DLX 重复覆盖
- (中等) HDU 5046 Airport ,DLX+可重复覆盖+二分。
- HDU 2828 Lamp(DLX重复覆盖)
- HDU 3335 Divisibility(DLX求最多重复覆盖)
- SPOJ 1771&&DLX精确覆盖,重复覆盖
- [DLX重复覆盖] fzu 1686 神龙的难题
- HDU 2295 Radar(DLX可重复覆盖)
- hdu 3957 Street Fighter 重复覆盖+精确覆盖 DLX
- DLX模板之精确覆盖和重复覆盖
- FOJ 1686 【DLX 可重复覆盖的DLX】
- HDU 3957 Street Fighter (最小支配集 DLX 重复覆盖+精确覆盖 )
- hdu 2295 Radar(重复覆盖,二分+DLX)
- hdu - 3498 - whosyourdaddy(重复覆盖DLX)
- FZU 1686 神龙的难题(DLX可重复覆盖)
- fzu 1686(DLX 重复点覆盖)
- 2013 ACM/ICPC Asia Regional Chengdu Online&hdu4735Little Wish~ lyrical step~(DLX解重复覆盖)
- 可重复覆盖的DLX
- DLX 舞蹈链 精确覆盖+可重复覆盖
- 最新版dlx模板(精确覆盖+重复覆盖)
- HDU-5046 Airport(二分+DLX重复覆盖)