HDU 4924 Football Manager DP

本文探讨了如何在给定的人数中选择最佳的11人足球队阵容,以实现最高总评分。通过考虑球员的位置、能力值、喜好的相互作用,采用动态规划方法进行优化选择。

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

【题目大意】

一个足球队有4种位置,门将、前锋、中锋、后卫,每种位置的总人数确定。从n个人中选11个人组成足球队,要使得队伍的总评分最高。总评分计算方式如下:总评分分为两部分,sum_ca,sum_pa。如果一个人确定了位置,总评分将会加上对应的ca,pa。特别的,所有人有喜欢、不喜欢的关系,如果队内的两人喜欢,那么sum_ca将加上一个w,如果不喜欢,则减去w。总评分大小判断关系:可将sum_ca,sum_pa视为一个pair,前者优先级高。

【思路】

这个居然是DP......这个居然是DP......这个居然是DP......这个DP居然还不是很难......

首先枚举具体选的11个人,把额外的加分算出来。dp[ i ][ j ][ k ][ k1 ]表示前i个人已经确定了位置,门将有j人,前锋有k人,中锋有k1人,最高的评分。然后推一下就好了。因为时间很紧,需要加上最优化剪枝。另外,我们可以通过交换,使得dp没有开的那一维最可能的大,这样的极限状态只有11*2*4*4 == 352。

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100111222;
const double INFF=1e200;
const double eps=1e-8;
const int mod=1000000007;
const int NN=505;
const int MM=100010;
/* ****************** */

struct node
{
    bool fg[4];
    int ca[4],pa[4];
    void init()
    {
        memset(fg,false,sizeof(fg));
    }
}a[25];
int id_to[105];
int val[25][25];
int num[4];
bool fg;
int ans_ca,ans_pa;
int re[25];
pair<int,int> dp[12][3][5][5];


void goo()
{
    int ex=0,jian=0;
    int i,j,t,k,k1,t1,t2;
    int max_num[4];
    pair<int,int> temp;

    for(i=1;i<=11;i++)
        for(j=1;j<=11;j++)
        {
            ex += val[ re[i] ][ re[j] ];
        }

    memset(max_num,0,sizeof(max_num));
    for(i=1;i<=11;i++)
    {
        t=0;
        for(j=0;j<4;j++)
            if( a[ re[i] ].fg[j] )
            {
                t = max(t,a[re[i]].ca[j]);
                max_num[j]++;
            }
        jian+=t;
    }

    for(j=0;j<4;j++)
    {
        if(max_num[j]<num[j])
            return;
    }

    if(fg && ex+jian<ans_ca)
        return;


    for(i=0;i<=11;i++)
        for(j=0;j<=1;j++)
            for(k=0;k<=num[1];k++)
                for(k1=0;k1<=num[2];k1++)
                    dp[i][j][k][k1] = MP(-INF,-INF);

    dp[0][0][0][0] = MP(0,0);
    for(i=0;i<11;i++)
        for(j=0;j<=1;j++)
            for(k=0;k<=num[1];k++)
                for(k1=0;k1<=num[2];k1++)
                    if(dp[i][j][k][k1].first!=-INF)
                    {
                        t1 = dp[i][j][k][k1].first;
                        t2 = dp[i][j][k][k1].second;
                        if(a[re[i+1]].fg[0])
                        {
                            temp = MP(t1+a[re[i+1]].ca[0],t2+a[re[i+1]].pa[0]);
                            dp[i+1][j+1][k][k1]=max(dp[i+1][j+1][k][k1],temp);
                        }
                        if(a[re[i+1]].fg[1])
                        {
                            temp = MP(t1+a[re[i+1]].ca[1],t2+a[re[i+1]].pa[1]);
                            dp[i+1][j][k+1][k1]=max(dp[i+1][j][k+1][k1],temp);
                        }
                        if(a[re[i+1]].fg[2])
                        {
                            temp = MP(t1+a[re[i+1]].ca[2],t2+a[re[i+1]].pa[2]);
                            dp[i+1][j][k][k1+1]=max(dp[i+1][j][k][k1+1],temp);
                        }
                        if(a[re[i+1]].fg[3])
                        {
                            temp = MP(t1+a[re[i+1]].ca[3],t2+a[re[i+1]].pa[3]);
                            dp[i+1][j][k][k1]=max(dp[i+1][j][k][k1],temp);
                        }
                    }

    temp = dp[11][1][num[1]][num[2]];
    if(temp.first>-INF)
    {
        int cca = temp.first + ex;
        int ppa = temp.second;

        if(fg)
        {
            if(cca>ans_ca)
            {
                ans_ca = cca;
                ans_pa = ppa;
            }
            else if(cca == ans_ca)
                ans_pa = max(ans_pa,ppa);
        }
        else
        {
            fg=true;
            ans_ca = cca;
            ans_pa = ppa;
        }
    }

}

void dfs(int now,int deep,int ge)
{
    if(ge==11)
    {
        goo();
        return;
    }
    if(now==deep+1)
        return;

    //xuan
    re[ge+1]=now;
    dfs(now+1,deep,ge+1);

    //bu xuan
    if(ge+deep-now>=11)
        dfs(now+1,deep,ge);
}

void solve(int n)
{
    fg=false;

    dfs(1,n,0);

    if(fg)
    {
        printf("%d %d\n",ans_ca,ans_pa);
    }
    else
    {
        puts("Poor Manager!");
    }
}

int main()
{
    char op[50];
    int cas;
    int n,m,ge,ca,pa,id;
    int wei,i,j,w,u,v,t;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d",&n);

        memset(id_to,0,sizeof(id_to));

        for(i=1;i<=n;i++)
        {
            scanf("%d",&t);

            id_to[t] = i;

            scanf("%d",&ge);

            a[i].init();

            for(j=0;j<ge;j++)
            {
                scanf("%s%d%d",op,&ca,&pa);
                if(strcmp(op,"GK")==0)
                    wei = 0;
                else if(strcmp(op,"DF")==0)
                    wei = 1;
                else if(strcmp(op,"MF")==0)
                    wei = 2;
                else
                    wei = 3;

                if(a[i].fg[wei])
                {
                    if(ca>a[i].ca[wei])
                    {
                        a[i].ca[wei] = ca;
                        a[i].pa[wei] = pa;
                    }
                    else if(ca==a[i].ca[wei])
                        a[i].pa[wei] = max(a[i].pa[wei], pa);
                }
                else
                {
                    a[i].fg[wei] = true;
                    a[i].ca[wei] = ca;
                    a[i].pa[wei] = pa;
                }
            }
        }

        memset(val,0,sizeof(val));
        scanf("%d",&m);
        for(i=0;i<m;i++)
        {
            scanf("%d%d%s%d",&u,&v,op,&w);

            u = id_to[u];
            v = id_to[v];

            if(op[0]=='D')
            {
                val[v][u]-=w;
            }
            else
            {
                val[v][u]+=w;
            }
        }


        num[0]=1;
        scanf("%d-%d-%d",&num[1],&num[2],&num[3]);

        id=3;
        if(num[1]>num[2] && num[1]>num[3])
            id=1;
        if(num[2]>num[1] && num[2]>num[3])
            id=2;

        swap(num[id],num[3]);
        for(i=1;i<=n;i++)
        {
            swap(a[i].fg[id],a[i].fg[3]);
            swap(a[i].ca[id],a[i].ca[3]);
            swap(a[i].pa[id],a[i].pa[3]);
        }

        solve(n);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值