题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3720
题意:有4种一共23球员,需要选出10个球员组成4-4-2 阵容和1个守门员,每个球员都有能力值,以及2个球员之间可能会有combin,额外增加或者减少能力值
思路:一开始就想到了dfs,但是很蠢的选择了递推到11层,每层从23个球员进行挑选的方式,后来看了题解……进行了剪枝,每个球员只有选择和不选择2种情况,一共23层,每层只有2个分支,要注意的是combin可能导致res为负,初始化要注意(看了下自己写的代码蠢到无法直视)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#define inf 0x3f3f3f3f
using namespace std;
struct Hum
{
int val,k;
string name;
}s[50];
char ball[30];
int kind[5],num[5]={1,4,4,2},com[30][30];vis[50],kvis[5],res;
void dfs(int n,int m,int abi)
{
if (n==11)
{
res=max(abi,res);
return;
}
if (m>=23) return;
dfs(n,m+1,abi);
if (kvis[s[m].k]<num[s[m].k])
{
int change=0;
vis[m]=1;
kvis[s[m].k]++;
for (int i=0;i<26;i++)
{
if (vis[i] && com[m][i]!=0)
{
change+=com[m][i];
}
}
abi=abi+s[m].val+change;
dfs(n+1,m+1,abi);
abi=abi-s[m].val-change;
kvis[s[m].k]--;
vis[m]=0;
}
}
int main()
{
int t,n;
while (cin>>s[0].name)
{
scanf("%d %s",&s[0].val,&ball);
if (ball[0]=='g')
{
kind[0]++;
s[0].k=0;
}
else if (ball[0]=='d')
{
kind[1]++;
s[0].k=1;
}
else if (ball[0]=='m')
{
kind[2]++;
s[0].k=2;
}
else if (ball[0]=='s')
{
kind[3]++;
s[0].k=3;
}
res=-inf;
memset(com,0,sizeof(com));
memset(vis,0,sizeof(vis));
memset(kvis,0,sizeof(kvis));
memset(kind,0,sizeof(kind));
for (int i=1;i<23;i++)
{
int tem;
cin>>s[i].name;
scanf("%d %s",&s[i].val,&ball);
if (ball[0]=='g')
{
kind[0]++;
s[i].k=0;
}
else if (ball[0]=='d')
{
kind[1]++;
s[i].k=1;
}
else if (ball[0]=='m')
{
kind[2]++;
s[i].k=2;
}
else if (ball[0]=='s')
{
kind[3]++;
s[i].k=3;
}
}
scanf("%d",&n);
for (int i=0;i<n;i++)
{
string x,y;
int xx,yy,tem;
cin>>x>>y>>tem;
for (int j=0;j<23;j++)
{//
if (x==s[j].name) xx=j;
if (y==s[j].name) yy=j;//cout<<s[j].name<<":"<<y<<endl;
}
com[xx][yy]=tem;
com[yy][xx]=tem;
}
if (kind[0]<1 || kind[1]<4 || kind[2]<4 || kind[3]<2)
{
cout<<"impossible"<<endl;
continue;
}
dfs(0,0,0);
cout<<res<<endl;
}
}