NOIP2010第四题 ---三国游戏(摘自洛谷题解)

来源:互联网 发布:淘宝家居排行榜 编辑:程序博客网 时间:2024/05/17 04:14

一、题目描述

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

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

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

的武将组合代表自己的军队进行二对二比武,拥有更高默契值的一对武将组合获胜,表示两军交战,拥有获胜武将组合的一方获胜。

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

双方选将过程如下所示:

小涵想知道,如果计算机在一局游戏中始终坚持上面这个策略,那么自己有没有可能必胜?如果有,在所有可能的胜利结局中,自己那对用于比武的武将组合的默契值最大是多少? 假设整个游戏过程中,对战双方任何时候均能看到自由武将队中的武将和对方军队的武将。为了简化问题,保证对于不同的武将组合,其默契值均不相同。

输入输出格式

输入格式:

输入文件名为 sanguo.in,共 N 行。

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

第 2 行到第 N 行里,第(i+1)行有(Ni)个非负整数,每两个数之间用一个空格隔

开,表示 i 号武将和 i+1,i+2,……,N 号武将之间的默契值(0≤默契值≤1,000,000,000)。

输出格式:

输出文件 sanguo.out 共 1 或 2 行。

若对于给定的游戏输入,存在可以让小涵获胜的选将顺序,则输出 1,并另起一行输出

所有获胜的情况中,小涵最终选出的武将组合的最大默契值。

如果不存在可以让小涵获胜的选将顺序,则输出 0。

输入输出样例

输入样例#1: 复制
6 5 28 16 29 27 23 3 20 1 8 32 26 33 11 12 
输出样例#1: 复制
132





输入样例#2: 复制
8 42 24 10 29 27 12 58 31 8 16 26 80 6 25 3 36 11 5 33 20 17 13 15 77 9 4 50 19 
输出样例#2: 复制
177














说明

【数据范围】

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

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

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

二、解题思路

解答本题,必须看清题意,知道以下几点:

一、只需要选两次,由于比胜负靠的是双方武将中默契值最大的一对,所以除了默契值最大的一对,其他的武将都是没

用的。并因为小涵先选,并且题目要求输出默契值尽量大的。所以必须两次定胜负,只要一开始选择最优方案,之后也

就可以不用考虑了。

二、再深入分析,就会发现,小涵是输不了的。这是因为小涵永远掌握主动权,计算机一直都只是应付小涵,且大家可

以举例证明——小涵选一个将,计算机选走搭配默契值最大的武将,然后小涵选走默契值次大的武将,计算机把小涵选

走的两个武将中剩下搭配方案里默契值最大的选走。到这里就已经定下了胜负。此时,如果计算机的最大默契值比小涵

的小,那么毫无疑问小涵就赢了。而如果计算机的武将搭配默契值比小涵的大,那么小涵完全可以换方法选,从计算机

的方案的角度选,得到更优方案。依此类推,必定能赢。所以无论如何,小涵总会赢,我们可以直接把那个“1”输出

来。大家如果光看我的描述不能理解,可以自己举例子仿照样例画一张表,就能理解了。

三、逐步分析所有情况,会发现。在一个武将和其他所有武将的搭配方案中,默契值最大的是拿不到的。因为小涵不能

一下选两个,计算机又要和小涵抢。得到默契值最大的搭配方案,那是不可能的,想都别想。但是,小涵也没有这么悲

剧,这个游戏规则也有对小涵有利的一面。在一个武将和其他武将的搭配中,默契值次大的那对,小涵可以稳拿。因为

计算机会死板地被默契值最大的那对引开。这样搭配后默契值次大的武将,小涵就可以轻而易举地获得。

这道题只需要找到每个人所有默契值中第二大的中最大的,听上去很绕,其实很简单。

思路也很好理解:最开始我们可以选择一个角色,计算机一定会把与其相匹配默契值最大的那个角色给堵上(不妨称一个角色和与他默契值最大的角色为“最大组合”),即:

无论如何都取不到一个人的最大组合。

所以说,退而求其次,尽可能取到所有次大默契值中的最大者,这样的话,只要在接下来的选择中不让计算机选取到最大组合就必定获胜。

三、参考代码:

#include <iostream>

#include <algorithm>

using namespace std;

long long map[501][501], ans[501];//为了省事,map[i][j]表示i与j的默契值

int main() {

    int n;

    cin >> n;

    for (int i = 1; i<= n; i++) {

        for (int j = i + 1; j<= n; j++) {

            cin >> map[i][j];

            map[j][i] = map[i][j];

        }

        sort(map[i] + 1, map[i] + n+ 1);//即将所有map[i]从小到大排序

        ans[i] = map[i][n- 1];//将其中第二小的放入ans数组

    }

    sort(ans + 1, ans+ n + 1);//再将ans数组排序,输出最大者即可

    cout << "1" << endl<< ans[n] << endl;

    return 0;

}



  

阅读全文
0 0
原创粉丝点击