hdu 3720 暴力枚举

本文介绍了一种通过编程方式来优化足球比赛阵容的选择方法。基于球员的能力值和特殊配合效果,利用暴力枚举的方法实现最优阵容的选择。文章提供了完整的代码示例,并详细解释了关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CLICK HERE

Problem 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 j are 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
这道题直接用暴力解决;注意几个点:
(1)将那些重复使用的语句编程函数,不然代码特别长;
(2)事先算出四个位置的人数,然后for循环暴力枚举
附上代码:
#include <iostream>
#include <string.h>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstdio>
const int MAX=100000000;
using namespace std;
int addition[25][25];//用于存储附加值
int ans[20],cnt;//ans用于记录所选中的11个位置,然后枚举这十一个位置求和
int d,g,m,s; //分别表示defender,goalkeeper,midfielder,striker四种位置数量
struct node
{
 char name[50];  //
 char position[50];
 int p;
}player[30];
bool cmp(node a,node b)   //将字符串从小到大排序
{
 return strcmp(a.position,b.position)<0;
}
int find(char *s)    
{
 for(int i=1;;i++)
   if(strcmp(s,player[i].name)==0)
      return i;
}
void set(char c)
{
  if(c=='d')d++;
  else if(c=='g')g++;
  else if(c=='m')m++;
  else if(c=='s')s++;
}
int cal()//枚举求和
{
 int ret=0;
 for(int i=1;i<=11;i++)
  {
   ret+=player[ans[i]].p;
   for(int j=i+1;j<=11;j++)
    ret+=addition[ans[i]][ans[j]];
  }
 return ret;
}
void sove()
{
 for(int a=1;a<=d;a++)
  for(int b=a+1;b<=d;b++)
   for(int c=b+1;c<=d;c++)
    for(int e=c+1;e<=d;e++)
    {
      ans[1]=a;
      ans[2]=b;
      ans[3]=c;
      ans[4]=e;
      for(int aa=d+1;aa<=g+d;aa++)
      {
        ans[5]=aa;
        for(int bb=g+d+1;bb<=g+d+m;bb++)
         for(int cc=bb+1;cc<=g+d+m;cc++)
          for(int ee=cc+1;ee<=g+d+m;ee++)
           for(int aaa=ee+1;aaa<=g+d+m;aaa++)
           {
            ans[6]=bb;
            ans[7]=cc;
            ans[8]=ee;
            ans[9]=aaa;
            for(int i=g+d+m+1;i<=23;i++)
             for(int j=i+1;j<=23;j++)
             {
               ans[10]=i;
               ans[11]=j;
               cnt=max(cnt,cal());
             }
            }
      }

    }
}

int main()
{
 char s1[50],s2[50];
 int temp,qq;
 while(scanf("%s%d%s",player[1].name,&player[1].p,player[1].position)!=EOF)
 {
   d=g=m=s=0;
   set(player[1].position[0]);
   for(int i=2;i<=23;i++)
     {scanf("%s%d%s",player[i].name,&player[i].p,player[i].position);
      set(player[i].position[0]);
     }
   sort(player+1,player+24,cmp);
   memset(addition,0,sizeof(addition));
   memset(ans,0,sizeof(ans));
   cin>>qq;
   while(qq--)
   {
      scanf("%s%s%d",s1,s2,&temp);
      int x=find(s1);
      int y=find(s2);
      addition[x][y]=addition[y][x]=temp;
   }

   //判读能否组队

   if(d<4||g<1||m<4||s<2)
   {
     printf("impossible\n");
     continue;
   }
   cnt=-MAX;
   sove();
   printf("%d\n",cnt);

 }
 return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值