G - Arranging Your Team

G - Arranging Your Team
Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

Your country has qualified for the FIFA 2010 South Africa World Cup. As the coach, you have made up the 23 men squad. Now you must select 11 of them as the starters. As is well known, there are four positions in soccer: goalkeeper, defender, midfielder and striker. Your favorite formation is 4-4-2, that is, you should choose 4 defenders, 4 midfielders, 2 strikers, and of course, 1 goalkeeper. As a retired ACMer, you want to write a program to help you make decision. Each person's ability has been evaluated as a positive integer. And what's more, for some special pairs of persons, if the two people are both on the field, there will be an additional effect (positive or negative). Now you should choose the 11 persons to make the total value maximum.
 

Input

There are multiple test cases, separated by an empty line. The first 23 lines of each test case indicate each person's name S  i, ability value V  i, and position. The length of each name is no more than 30, and there are no whitespaces in the names. All the names are different. The ability values are positive integers and no more than 100. The position is one of "goalkeeper", "defender", "midfielder" and "striker". 

Then an integer M indicates that there are M special pairs. Each of the following M lines contains S  i, S  j and C  ij, means that if S  i and S  jare both on the field, the additional profit is C  ij. (-100 ≤ C  ij ≤ 100). S  i and S  j are different strings, and must be in the previous 23 names. All the (S  i, S  j) pairs 
are different. 
 

Output

Output one line for each test case, indicating the maximum total ability values, that is, the total ability values of the 11 persons plus the additional effects. If you cannot choose a 4-4-2 formation, output "impossible" instead.
 

Sample Input

     
     
Buffon 90 goalkeeper De_Sanctis 80 goalkeeper Marchetti 80 goalkeeper Zambrotta 90 defender Cannavaro 90 defender Chiellini 90 defender Maggio 90 defender Bonucci 80 defender Criscito 80 defender Bocchetti 80 defender Pirlo 90 midfielder Gattuso 90 midfielder De_Rossi 90 midfielder Montolivo 90 midfielder Camoranesi 80 midfielder Palombo 80 midfielder Marchisio 80 midfielder Pepe 80 midfielder Iaquinta 90 striker Di_Natale 90 striker Gilardino 80 striker Quagliarella 80 striker Pazzini 80 striker 1 Pirlo Quagliarella 50 ZhangSan01 50 goalkeeper ZhangSan02 50 defender ZhangSan03 50 defender ZhangSan04 50 defender ZhangSan05 50 defender ZhangSan06 50 defender ZhangSan07 50 defender ZhangSan08 50 defender ZhangSan09 50 defender ZhangSan10 50 defender ZhangSan11 50 defender ZhangSan12 50 defender ZhangSan13 50 defender ZhangSan14 50 defender ZhangSan15 50 defender ZhangSan16 50 midfielder ZhangSan17 50 midfielder ZhangSan18 50 midfielder ZhangSan19 50 midfielder ZhangSan20 50 midfielder ZhangSan21 50 midfielder ZhangSan22 50 midfielder ZhangSan23 50 midfielder 0
 

Sample Output

     
     
1030 impossible


题目会给你23个球员的姓名、分数、定位。定位一共有4种,g,d,m,s。对应每种定位需要选的人数是1 4 4 2,如果不能达到就输出impossible,如果能达到就输出能够获得的最高分。


题目还定义了加分设定,如果会给出很多对选手,如果他们同时上场则有分数的加成。


思路,因为最多只有23个球员,dfs暴力即可,对于统计分数加成可以将姓名hash掉或者map为一个数字然后用数组保存。


因为DFS写得有点丑陋,所以WA了一发,顺便这道题有坑点就是分数可能为负,所以ANS初始化应该为-INF。


#include"iostream"
#include"cstring"
#include"cstdio"
#include"string"
#include"map"
#include"algorithm"

#define INF 0x7f7f7f7f

using namespace std;

struct node
{
    string name;
    char pos;
    int point;
}man[25];

int add[25][25];
map<string,int> mp;
int num;
int numg,numd,numm,nums;
int ans;
bool vis[25];

void dfs(int nowg,int nowd,int nowm,int nows,int score,int id)
{
    if(id == 25) return;
    if(nowg == 1 && nowd == 4 && nowm == 4 && nows == 2)
    {
        ans = max(ans,score);
        return;
    }
    if(man[id].pos == 'g' && nowg < 1)
    {
        int ad = 0;
        for(int i = 1;i <= 23;i++)
        {
            if(vis[i]) ad += add[id][i];
        }
        vis[id] = true;
        dfs(nowg+1,nowd,nowm,nows,score+man[id].point+ad,id+1);
        vis[id] = false;
        dfs(nowg,nowd,nowm,nows,score,id+1);
    }
    else if(man[id].pos == 'd' && nowd < 4)
    {
        int ad = 0;
        for(int i = 1;i <= 23;i++)
        {
            if(vis[i]) ad += add[id][i];
        }
        vis[id] = true;
        dfs(nowg,nowd+1,nowm,nows,score+man[id].point+ad,id+1);
        vis[id] = false;
        dfs(nowg,nowd,nowm,nows,score,id+1);
    }
    else if(man[id].pos == 'm' && nowm < 4)
    {
        int ad = 0;
        for(int i = 1;i <= 23;i++)
        {
            if(vis[i]) ad += add[id][i];
        }
        vis[id] = true;
        dfs(nowg,nowd,nowm+1,nows,score+man[id].point+ad,id+1);
        vis[id] = false;
        dfs(nowg,nowd,nowm,nows,score,id+1);
    }
    else if(man[id].pos == 's' && nows < 2)
    {
        int ad = 0;
        for(int i = 1;i <= 23;i++)
        {
            if(vis[i]) ad += add[id][i];
        }
        vis[id] = true;
        dfs(nowg,nowd,nowm,nows+1,score+man[id].point+ad,id+1);
        vis[id] = false;
        dfs(nowg,nowd,nowm,nows,score,id+1);
    }
    else dfs(nowg,nowd,nowm,nows,score,id+1);
}

int main(void)
{
    string s,pos;
    int p;
    while(cin >> s >> p >> pos)
    {
        num = numg = numd = numm = nums = 0;
        ans = -INF;
        memset(add,0,sizeof(add));
        memset(vis,false,sizeof(vis));
        if(pos[0] == 'g')
        {
            ++numg;
            man[1].name = s;
            man[1].pos = 'g';
            man[1].point = p;
        }
        else if(pos[0] == 'd')
        {
            ++numd;
            man[1].name = s;
            man[1].pos = 'd';
            man[1].point = p;
        }
        else if(pos[0] == 'm')
        {
            ++numm;
            man[1].name = s;
            man[1].pos = 'm';
            man[1].point = p;
        }
        else
        {
            ++nums;
            man[1].name = s;
            man[1].pos = 's';
            man[1].point = p;
        }
        mp[s] = 1;
        for(int i = 2;i <= 23;i++)
        {
            cin >> s >> p >> pos;
            mp[s] = i;
            if(pos[0] == 'g')
            {
                ++numg;
                man[i].name = s;
                man[i].pos = 'g';
                man[i].point = p;
            }
            else if(pos[0] == 'd')
            {
                ++numd;
                man[i].name = s;
                man[i].pos = 'd';
                man[i].point = p;
            }
            else if(pos[0] == 'm')
            {
                ++numm;
                man[i].name = s;
                man[i].pos = 'm';
                man[i].point = p;
            }
            else
            {
                ++nums;
                man[i].name = s;
                man[i].pos = 's';
                man[i].point = p;
            }
        }
        int nn;
        scanf("%d",&nn);
        while(nn--)
        {
            string s1,s2;
            int adp;
            cin >> s1 >> s2 >> adp;
            add[mp[s1]][mp[s2]] = adp;
            add[mp[s2]][mp[s1]] = adp;
        }

        //for(int i = 1;i <= 23;i++) cout << man[i].pos << endl;
        //for(int i = 1;i <= 23;i++) cout << man[i].point << endl;

        if(numg < 1 || numd < 4 || numm < 4 || nums < 2)
        {
            printf("impossible\n");
            continue;
        }

        dfs(0,0,0,0,0,1);
        printf("%d\n",ans);
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值