http://acm.timus.ru/problem.aspx?space=1&num=1208题目大意:给出n个队,n<=18, 每队包含三个人名,求n个队中最多选出几个队,选出的队中的人名不重复。
思路:i队和j队,如果有相同名字的队员,则连一无向边i-j,题目变为求给定无向图G的最大独立集,由于n不大,直接建图暴力枚举的。O(n*2^n)复杂度。
Code:
#include<cstdio>
#include<cstring>
#include<cstdlib>
struct Node{
char member[3][21];
}teamSet[20];
int n;
unsigned int graph[21][21];
unsigned int teams[20];
unsigned int isOk(int I, int J){
int i = 0;
int j = 0;
unsigned int flag = 0;
for(i = 0; i < 3 && !flag; i++){
for(j = 0; j < 3; j++){
if(!strcmp(teamSet[I].member[i], teamSet[J].member[j])){
flag = 1;
break;
}
}
}
return flag;
}
int Check(unsigned int team){
unsigned int c = 0;
unsigned int tempSet = 0;
int nCount = 0;
int num = n;
int isValid = 1;
c = 0x00020000;
while(num++ < 18){
c >>= 1;
}
for(num = n; c > 0; c >>= 1, num--){
if(c&team){
nCount++;
if(tempSet&c){
isValid = 0;
break;
}
tempSet |= teams[n - num + 1];
}
}
return (1 == isValid) ? nCount : -1;
}
int main(int argc, char* argv[], char* env[])
{
int i = 0;
int j = 0;
int t = 0;
int maxTeams = 0;
unsigned int c = 0;
unsigned int tempN = 0;
while(scanf("%d", &n) != EOF){
for(i = 1; i <= n; i++){
scanf("%s%s%s", teamSet[i].member[0],
teamSet[i].member[1], teamSet[i].member[2]);
}
for(i = 1; i <= n; i++){
graph[i][i] = 0;
for(j = i + 1; j <= n; j++){
graph[i][j] = graph[j][i] = isOk(i, j);
}
}
for(i = 1; i <= n; i++){
teams[i] = graph[i][j];;
for(j = 2; j <= n; j++){
teams[i] <<= 1;
teams[i] |= graph[i][j];
}
}
maxTeams = 0;
tempN = 1 << n;
for(c = 1; c < tempN; c++){
t = Check(c);
if(t > maxTeams){
maxTeams = t;
}
}
printf("%d\n", maxTeams);
}
return 0;
}
posted on 2011-07-21 17:44
Lshain 阅读(306)
评论(0) 编辑 收藏 引用 所属分类:
Algorithm 、
题解-timus