hdu 4924 Football Manager(dp)

题目链接

Football Manager

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 333    Accepted Submission(s): 51


Problem Description
Football Manager is a series of football management simulation games developed by Sports Interactive and published by Sega. In this game, you will play a role of a football club manager and conduct your team to chase championship titles. As a football team manager, you need to take responsibilities for tactics developing, training arrangements, on-pitch commanding, player trading, etc. One of the most important things is to select your starting line-up.

According to the rules of football matches, there should be 11 players in your starting line-up, where one of them must be a goalkeeper. Besides the goalkeeper (GK), there’re three classes of positions: defender (DF), midfielder (MF), and striker (ST).

When a manager is selecting his starting line-up, he usually determines the formation first. The football formation is usually noted like “4-4-2”“4-5-1”“4-3- 3”, etc. For example, the “4-5-1” formation denotes that there are 4 defenders, 5 midfielders and 1 striker. Note that every player has his preferred positions, and they will always refuse to appear at positions he does not prefer, while some excellent players may be qualified for several positions. For example, C. Ronaldo can play as both a striker and a midfielder.

In the game, players have two important attributes for each of his preferred positions: CA (current ability) and PA (potential ability). The CA of the line-up is defined as the sum of the 11 players’ CA in the formation. Similar to CA, the PA of the line-up equals to the sum of 11 players’ PA. Then your task is to select the proper players to reach maximum CA of your line-up. When a tie occurs, the one of maximum PA is required.

Beyond these requirements and limits, the relationships between players also make sense to the CA of your line-up. Every player may like or dislike some of his teammates. When he and the one he likes are both on the pitch, the CA of the line-up will be increased by a specific value. On the contrary, when someone and his disliked player occurs on the pitch concurrently, the line-up’s CA will be decreased. Be careful that the like and dislike relationships between players are unidirectional. Not surprisingly, Plane.Gao likes Messi very much while Messi may not know Plane.Gao at all.
 

Input
The input contains multiple test cases. The first line of input gives the number of test cases T (1<=T<=20).

For each test case, the first line contains an integer N (1<=N<=20), the total number of players in your team.

Each of the following N lines describe a player in the following format:
<SquadNum> <PositionNum> <pos 1> <CA 1> <PA 1> <pos 2> <CA 2> <PA 2> . . . <pos num><CA num><PA num>
Here:
<SquadNum> denotes the player’s unique squad number (between 1 and 99, inclusive).
<PositionNum> denotes the number of positions he preferred.
<pos 1> <pos 2> . . . <pos num> are strings chosen in {GK, DF, MF, ST},denoting all his preferred positions.
<CA i> denotes his CA at <pos i>.
<PA i> denotes his PA at <pos i>.
(0<=|P A i|,|C A i|<=1000, note P A and CA can be negative here.)
After the description of the player list, the following line will give an integer M (0<=M<=N (N - 1)), which indicates the number of relationships between the teammates. Then each of the following M lines is shown in the following format:
<SquadNum A> <SquadNum B > Like/Dislike <value>
Here:
<SquadNum A> denotes Player A’s Squad Number.
<SquadNum B> denotes Player B’s Squad Number.
Like/Dislike denotes the property of the relationship.
<value> denotes that when both of them appear in your starting line-up, the CA of line-up will be increased/decreased by value(0<=value<=100).
No two relationships of the same pair of teammates will occur.
The last line of each test case shows the formation that you have determined. We guarantee that the formation is legal.
You may take the sample for more details.
 

Output
For each test case, you should output two integers in a line, the best CA and PA of your line-up. If you can even not round up your line-up, please output “Poor Manager!” (without quotes)
 

Sample Input
  
  
2 15 1 1 GK 150 160 2 1 DF 150 160 3 1 DF 150 160 4 1 DF 150 160 5 1 DF 150 160 6 1 MF 150 160 7 1 MF 150 160 8 1 MF 150 160 9 1 ST 150 160 10 1 MF 150 160 11 1 ST 150 160 12 1 GK 130 150 13 1 DF 130 150 14 1 MF 130 150 15 1 ST 130 150 2 15 9 Like 10 2 13 Dislike 20 4-4-2 11 1 1 GK 150 160 2 1 DF 150 160 3 1 DF 150 160 4 1 DF 150 160 5 1 DF 150 160 6 1 MF 150 160 7 1 MF 150 160 8 1 MF 150 160 9 1 ST 150 160 10 1 MF 150 160 11 1 ST 150 160 0 4-3-3
 

Sample Output
  
  
1650 1760 Poor Manager!
 

Author
BUPT
题意:N个球员,告诉每个球员的编号和他能踢的位置,以及他踢每个位置的能力值和潜力值。告诉你阵型,现在要选11个人组成首发,让能力值的和最大,如果能力值相同让潜力值最大。但是球员与球员直接有相互影响关系。在选出来的首发中,假设一个球员喜欢与另一个球员踢球,那么总能力值增加,反之减少。N<=20。

题解:首先从20个人中选出11个人来,对于已经选出来的11个人用dp来算最优解。dp【i】【GK】【DF】【MF】表示前i个人GK位置有GK个人,DF位置有DF个人,MF位置有MF个人,用i-GK-DF-MF表示位置ST的人数,转移显然。但是复杂度略高,需要优化。首先我们可以将ST映射到人数最多的一维。然后再加上可行性剪枝和最优性剪枝。对于可行性剪枝,可以先判断选出来的11个人能不能构造出阵型,不能则减掉。对于最优性剪枝,假设每个人的都取他的最大能力值,判断这样可不可能更新答案,如果这样都不能减掉就是了。这题还有很丧心病狂的地方,会有球员自己喜欢自己或不喜欢自己的数据。害我查了一个晚上。。。代码如下:(姿势不好跑得略慢。。。)

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<string>
#include<math.h>
#include<stdlib.h>
#define nn 110
#define inff 0x3fffffff
using namespace std;
int n,m;
struct node
{
    int id;
    pair<int,int>nl;
}tem;
int len[25];
node ve[25][10];
int bh[110];
int gx[25][25];
int ys1,ys2,ys3;
int z1,z2,z3;
int a[20];
int ans,ans1;
pair<int,int>dp[25][10][10][10];
void init()
{
    ans=ans1=-inff;
    memset(len,0,sizeof(len));
    memset(gx,0,sizeof(gx));
}
void update(int i,int j,int k,int g,pair<int,int>x,pair<int,int>y)
{
    pair<int,int> &f=dp[i][j][k][g];
    if(f.first<x.first+y.first)
    {
        f.first=x.first+y.first;
        f.second=x.second+y.second;
    }
    else if(f.first==x.first+y.first)
    {
        f.second=max(f.second,x.second+y.second);
    }
}
void DP()
{
    int i,j,k,g,e;
    int gg=0;
    for(i=1;i<=11;i++)
    {
        for(j=i;j<=11;j++)
        {
            gg+=gx[a[i]][a[j]];
        }
    }
    int w0,w1,w2,w3;
    w0=w1=w2=w3=0;
    int ix=0,mx;
    for(i=1;i<=11;i++)
    {
        mx=-inff;
        for(j=0;j<len[a[i]];j++)
        {
            tem=ve[a[i]][j];
            mx=max(mx,tem.nl.first);
            if(tem.id==0)
                w0++;
            else if(tem.id==ys1)
                w1++;
            else if(tem.id==ys2)
                w2++;
            else
                w3++;
        }
        ix+=mx;
    }
    if(w0<1||w1<z1||w2<z2||w3<z3)
        return ;
    if(ix+gg<ans)
        return ;
    for(i=0;i<=11;i++)
    {
        for(j=0;j<=1;j++)
        {
            for(k=0;k<=z1;k++)
            {
                for(g=0;g<=z2;g++)
                {
                    dp[i][j][k][g]=make_pair(-inff,-inff);
                }
            }
        }
    }
    dp[0][0][0][0]=make_pair(0,0);
    for(i=0;i<11;i++)
    {
        for(j=0;j<=1;j++)
        {
            for(k=0;k<=z1;k++)
            {
                for(g=0;g<=z2;g++)
                {
                    if(i<j+k+g)
                        break;
                    if(dp[i][j][k][g].first==-inff)
                        continue;
                    for(e=0;e<len[a[i+1]];e++)
                    {
                        tem=ve[a[i+1]][e];
                        if(tem.id==0&&j<1)
                        {
                            update(i+1,j+1,k,g,dp[i][j][k][g],tem.nl);
                            continue;
                        }
                        if(tem.id==ys1&&k<z1)
                        {
                            update(i+1,j,k+1,g,dp[i][j][k][g],tem.nl);
                            continue;
                        }
                        if(tem.id==ys2&&g<z2)
                        {
                            update(i+1,j,k,g+1,dp[i][j][k][g],tem.nl);
                            continue;
                        }
                        if(tem.id==ys3&&i-j-k-g<z3)
                        {
                            update(i+1,j,k,g,dp[i][j][k][g],tem.nl);
                            continue;
                        }
                    }
                }
            }
        }
    }
    if(dp[11][1][z1][z2].first+gg>ans)
    {
        ans=dp[11][1][z1][z2].first+gg;
        ans1=dp[11][1][z1][z2].second;
    }
    else if(dp[11][1][z1][z2].first+gg==ans)
    {
        ans1=max(ans1,dp[11][1][z1][z2].second);
    }
}
void dfs(int id,int ren)
{
    if(ren==11)
    {
        DP();
        return ;
    }
    if(id>n)
        return ;
    for(int i=id;i<=n;i++)
    {
        if(ren+n-i+1>=11)
        {
            a[ren+1]=i;
            dfs(i+1,ren+1);
        }
    }
}
int main()
{
    int t;
    char s[20];
    int i,num,ca,pa,u,v,l,x;
    int cas=1;
    scanf("%d",&t);
    while(t--)
    {
        init();
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&num);
            bh[x]=i;
            while(num--)
            {
                scanf("%s%d%d",s,&ca,&pa);
                if(s[0]=='G')
                    tem.id=0;
                else if(s[0]=='D')
                    tem.id=1;
                else if(s[0]=='M')
                    tem.id=2;
                else
                    tem.id=3;
                tem.nl=make_pair(ca,pa);
                ve[i][len[i]++]=tem;
            }
        }
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d%d%s%d",&u,&v,s,&l);
            if(s[0]=='L')
            {
                gx[bh[u]][bh[v]]+=l;
                if(u!=v)
                    gx[bh[v]][bh[u]]+=l;
            }
            else
            {
                gx[bh[u]][bh[v]]-=l;
                if(u!=v)
                    gx[bh[v]][bh[u]]-=l;
            }
        }
        scanf("%d-%d-%d",&z1,&z2,&z3);
        ys1=1,ys2=2,ys3=3;
        if(z1>=z2&&z1>=z3)
        {
            swap(z1,z3);
            swap(ys1,ys3);
        }
        else if(z2>=z1&&z2>=z3)
        {
            swap(z2,z3);
            swap(ys2,ys3);
        }
        dfs(1,0);
        if(ans==-inff)
        {
            puts("Poor Manager!");
        }
        else
            printf("%d %d\n",ans,ans1);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值