洛谷 P1199 三国游戏 解题报告

P1199 三国游戏

题目描述

小涵很喜欢电脑游戏,这些天他正在玩一个叫做《三国》的游戏。

在游戏中,小涵和计算机各执一方,组建各自的军队进行对战。游戏中共有\(N\)位武将(\(N\)为偶数且不小于4),任意两个武将之间有一个“默契值”,表示若此两位武将作为一对组合作战时,该组合的威力有多大。游戏开始前,所有武将都是自由的(称为自由武将,一旦某个自由武将被选中作为某方军队的一员,那么他就不再是自由武将了),换句话说,所谓的自由武将不属于任何一方。

游戏开始,小涵和计算机要从自由武将中挑选武将组成自己的军队,规则如下:小涵先从自由武将中选出一个加入自己的军队,然后计算机也从自由武将中选出一个加入计算机方的军队。接下来一直按照“小涵→计算机→小涵→……”的顺序选择武将,直到所有的武将被双方均分完。然后,程序自动从双方军队中各挑出一对默契值最高的武将组合代表自己的军队进行二对二比武,拥有更高默契值的一对武将组合获胜,表示两军交战,拥有获胜武将组合的一方获胜。

已知计算机一方选择武将的原则是尽量破坏对手下一步将形成的最强组合,它采取的具体策略如下:任何时刻,轮到计算机挑选时,它会尝试将对手军队中的每个武将与当前每个自由武将进行一一配对,找出所有配对中默契值最高的那对武将组合,并将该组合中的自由武将选入自己的军队。 下面举例说明计算机的选将策略,例如,游戏中一共有6个武将,他们相互之间的默契值如下表所示:

双方选将过程如下所示:

小涵想知道,如果计算机在一局游戏中始终坚持上面这个策略,那么自己有没有可能必胜?如果有,在所有可能的胜利结局中,自己那对用于比武的武将组合的默契值最大是多少?

假设整个游戏过程中,对战双方任何时候均能看到自由武将队中的武将和对方军队的武将。为了简化问题,保证对于不同的武将组合,其默契值均不相同。

输入输出格式

输入格式:

\(N\)行。

第一行为一个偶数\(N\),表示武将的个数。

第2行到第\(N\)行里,第\(i+1\)行有\(N_i\)个非负整数,每两个数之间用一个空格隔开,表示\(i\)号武将和\(i+1,i+2,…,N\)号武将之间的默契值( 0≤默契值≤1,000,000,000 )。

输出格式:

共1或2行。

若对于给定的游戏输入,存在可以让小涵获胜的选将顺序,则输出1,并另起一行输出所有获胜的情况中,小涵最终选出的武将组合的最大默契值。如果不存在可以让小涵获胜的选将顺序,则输出0。

说明

【数据范围】

对于 40% 的数据有 N≤10 。

对于 70% 的数据有 N≤18 。

对于 100% 的数据有 N≤500 。


果然博弈论最暴露我的智商有多差了。。反正没想出来,只是隐隐约约感觉和次大值有关系

分析计算机的选将策略:任何时刻,轮到计算机挑选时,它会尝试将对手军队中的每个武将与当前每个自由武将进行一一配对,找出所有配对中默契值最高的那对武将组合,并将该组合中的自由武将选入自己的军队

由计算机的选将策略和默契值的互异性,人类是不可能取到对自己上一步走完之后的最优将了。

但我们也不可以让计算机拿到最优的,既然这样,我们不如就先让计算机把当前存在的最优边一个一个拆掉,我们每次取全局最优边的一个端点,则另一个端点会被机子选。

当这些最优边的端点重合的时候,为了不让端点落在机子那里,我们对最优边的端点的一个选取策略即是次大值较大的那个,这样当这个次大值成为全局最大的时候,一定可以被人拿走。

这也同样回答了第二问,答案即是全局次大值最大者。


Code:

#include <cstdio>
const int N=503;
int g[N][N],n;
void init()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
        {
            scanf("%d",&g[i][j]);
            g[j][i]=g[i][j];
        }
}
void work()
{
    int ans=0,mx=0,se=0;
    for(int i=1;i<=n;i++)
    {
        mx=0,se=0;
        for(int j=1;j<=n;j++)
            if(mx<g[i][j])
            {
                se=mx;
                mx=g[i][j];
            }
            else if(se<g[i][j])
                se=g[i][j];
        ans=ans>se?ans:se;
    }
    printf("1\n%d\n",ans);
}
int main()
{
    init();
    work();
    return 0;
}

2018.7.6

posted @ 2018-07-06 16:24  露迭月  阅读(529)  评论(0编辑  收藏  举报