题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3720
题目大意:
有23个人,告诉每个人的名字,能力值,以及踢球的位置。要求选出1个守门员,2个前锋,4个中场,4个后卫。给m个关系,该关系的两个人如果同时在场,就会得到相应的分数值va(注意va可以为负值)。求怎样安排使得在场的人总价值最大。
解题思路:
先处理出每种位置的人分布,然后枚举是哪几个人,凑成后更新总价值即可。注意va可能为负数。
代码:
#include<iostream> #include<cmath> #include<cstdio> #include<sstream> #include<cstdlib> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #include<stack> #include<list> #include<queue> #include<ctime> #include<bitset> #define eps 1e-6 #define INF 0x3f3f3f3f #define PI acos(-1.0) #define ll __int64 #define LL long long #define lson l,m,(rt<<1) #define rson m+1,r,(rt<<1)|1 #define M 1000000007 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define Maxn 30 map<string,int>nameid; vector<int>pos[5]; //pos[i]保存位置i的人员分布 map<string,int>posid; //位置的标号 int va[Maxn],add[Maxn][Maxn],ans; bool vis[Maxn]; int Cal() { int res=0; for(int i=1;i<=23;i++) //已选了哪些人 if(vis[i]) res+=va[i]; for(int i=1;i<=23;i++) //人之间关系的相互影响 for(int j=i+1;j<=23;j++) { if(vis[i]&&vis[j]) { res=res+add[i][j]; } } return res; } void dfs4(int num,int cur) { if(num==4) { ans=max(ans,Cal()); //已全部选完了 return ; } for(int i=cur;i<pos[4].size();i++) //从下一个开始选 { vis[pos[4][i]]=true; dfs4(num+1,i+1); vis[pos[4][i]]=false; } } void dfs3(int num,int cur) { if(num==4) { dfs4(0,0); return ; } for(int i=cur;i<pos[3].size();i++) { vis[pos[3][i]]=true; dfs3(num+1,i+1); vis[pos[3][i]]=false; } } void dfs2(int num,int cur) { if(num==2) { dfs3(0,0); return ; } for(int i=cur;i<pos[2].size();i++) { vis[pos[2][i]]=true; dfs2(num+1,i+1); vis[pos[2][i]]=false; } } void dfs1(int num,int cur) { if(num==1) { dfs2(0,0); return ; } for(int i=cur;i<pos[1].size();i++) { vis[pos[1][i]]=true; dfs1(num+1,i+1); vis[pos[1][i]]=false; } } int main() { posid["goalkeeper"]=1; //书名对应标号 posid["striker"]=2; posid["midfielder"]=3; posid["defender"]=4; string name,job; while(cin>>name) { nameid.clear(); for(int i=1;i<=4;i++) / pos[i].clear(); memset(add,0,sizeof(add)); nameid[name]=1; scanf("%d",&va[1]); cin>>job; pos[posid[job]].push_back(1); //该职业新增一人 for(int i=2;i<=23;i++) { cin>>name>>va[i]>>job; nameid[name]=i; //人的标号 pos[posid[job]].push_back(i);//先找到该位置标号,然后添加该人 } int m; scanf("%d",&m); while(m--) { string name2; int tmp; cin>>name>>name2>>tmp; //人之间的关系值 add[nameid[name]][nameid[name2]]=tmp; add[nameid[name2]][nameid[name]]=tmp; } if(pos[1].size()<1||pos[2].size()<2||pos[3].size()<4||pos[4].size()<4) { printf("impossible "); continue; } ans=-INF; memset(vis,false,sizeof(vis)); dfs1(0,0); printf("%d ",ans); } return 0; }