博弈(p1199)

P1199 [NOIP 2010 普及组] 三国游戏

题目描述

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

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

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

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

武将编号 1 2 3 4 5 6
1 \(5\) \(28\) \(16\) \(29\) \(27\)
2 \(5\) \(23\) \(3\) \(20\) \(1\)
3 \(28\) \(23\) \(8\) \(32\) \(26\)
4 \(16\) \(3\) \(8\) \(33\) \(11\)
5 \(29\) \(20\) \(32\) \(33\) \(12\)
6 \(27\) \(1\) \(26\) \(11\) \(12\)

双方选将过程如下所示:

小涵 轮到计算机时可选的自由武将 计算机 计算机选将说明
第一轮 \(5\) \(1,2,3,4,6\) \(\color{magenta}4\) 小涵手中的 \(5\) 号武将与 \(4\) 号的默契值最高,所以计算机选择 \(4\) 号。
第二轮 \(5,3\) \(1,2,6\) \(4,\color{magenta}1\) 小涵手中的 \(5\) 号和 \(3\) 号武将与自由武将中配对可产生的最大默契值为 \(29\),是由 \(5\) 号与 \(1\) 号配对产生的,所以计算机选择 \(1\) 号。
第三轮 \(5,3,6\) \(2\) \(4,1,\color{magenta}2\)

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

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

输入格式

\(N\) 行。

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

\(2\) 行到第 \(N\) 行里,第 \(i+1\) 行有 \(N-i\) 个非负整数,每两个数之间用一个空格隔开,表示 \(i\) 号武将和 $i+1,i+2,\dots,N $ 号武将之间的默契值(\(0 \le \text{默契值} \le 10^9\))。

输出格式

共一或二行。

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

输入输出样例 #1

输入 #1

6 
5 28 16 29 27 
23 3 20 1 
8 32 26 
33 11 
12

输出 #1

1
32

输入输出样例 #2

输入 #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

1
77

说明/提示

数据范围

对于 $ 40%$ 的数据有 \(N≤10\)

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

对于 \(100\%\) 的数据有 \(4\le N≤500\)。保证对于不同的武将组合,其默契值均不相同。

AC代码

贪心是计算机的选择而不是人的选择,实际上每次博弈在两个回合内就结束了,所以不用设计一个贪心的递归算法

#include<bits/stdc++.h>
using namespace std;
int a[501][501];

int main(){
    int n;
    cin>>n;
    for(int i=1;i<n;i++){
        for(int j=i+1;j<=n;j++){
            cin>>a[i][j];
            a[j][i]=a[i][j];
        }
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        sort(a[i]+1,a[i]+n+1);
        ans=max(ans,a[i][n-1]);
    }
    cout<<1<<endl;
    cout<<ans<<endl;
    return 0;
}
posted @ 2025-11-11 12:50  sadmax11  阅读(5)  评论(0)    收藏  举报