首页 > 其他 > 详细

洛谷 P1199 三国游戏 题解

时间:2020-03-22 17:31:55      阅读:58      评论:0      收藏:0      [点我收藏+]

原题链接

简要题意:

每两个武将都有一定的默契值。你和电脑轮流选择武将,电脑总会选择让你得不到最大默契值的那个武将;你要选择一种方法,使得你的最大默契值最大。如果会输给电脑则输出 \(0\),否则输出 \(1\) 和那个最大的默契值。

首先,人肯定比电脑聪明

如果你抱着骗分的态度

printf("0\n");

然后你会得到一个完美的 \(0pt\).

也就是说,始终存在某种方案,使得人可以胜利!

你会发现,电脑的选法是有些死板(但也有些道理)的,它总是会阻止你拿到最高的那个默契值。

所以,每行最大的默契值肯定不是你的。但也不是它的。为什么呢?

假设第 \(i\) 个武将和第 \(j\) 个武将拥有最高的默契值 \(k\).

此时如果你选了 \(i\) 和 \(j\) 中的一个,那么电脑会选另一个,\(k\) 就谁也不属于。

如果你一个也不选,电脑肯定也不会来选这两个,所以 \(k\) 仍然谁也不属于。

那么结论得到了,既然最大值抢不到,可不可以抢次大值?

比方说,\(i\) 号武将和 \(j\) 号武将仍有最高的默契值 \(k\),而 \(i\) 号武将和另一个 \(x\) 号武将有次大的默契值 \(y\).

此时你选了 \(i\),然后电脑把 \(j\) 拿走了,紧接着你再拿走 \(x\).

此时,在与 \(i\) 号武将的所有搭配中,你占了优势:因为最大值谁也没捞到,但你却捞到了次大值。

类似的,每一行的最大值都是谁也没捞到,但你却捞到了每一行的次大值。

首先你显然胜利了,其次,那么你搭配的最大值是多少呢?

显然,就是 每一行的次大值的最大值 。

技术分享图片

意思是,把每行的次大值搞出来,再这 \(n\) 个数中取最大值!

吐槽:数据太弱了。(爆搜都能拿 \(70pts\),这什么东西)

你可能觉得,把每一行开 \(\texttt{vector}\) 分别排序即可,取次大值打擂即可。

时间复杂度: \(O(n^2 \log n)\).

还真过了?

好,那加强一下。

对于 \(100 \%\) 的数据,\(N \leq 5 \times 10^3\).

你会发现,此时你要用 \(O(n)\) 的时间取出次大值。

你打擂法没学好吧,这还叫加强,我真是服了

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;

const int N=5e2+1;

inline int read(){char ch=getchar();int f=1;while(ch<‘0‘ || ch>‘9‘) {if(ch==‘-‘) f=-f; ch=getchar();}
	int x=0;while(ch>=‘0‘ && ch<=‘9‘) x=(x<<3)+(x<<1)+ch-‘0‘,ch=getchar();return x*f;}

int n,a[N][N];
int ans=0;

int main(){
	n=read();
	for(int i=1;i<n;i++)
	for(int j=1;j<=n-i;j++) {
		a[i][j+i]=read();
		a[j+i][i]=a[i][j+i];
	} for(int i=1;i<=n;i++) {
		int max1=0,max2=0; //max1 是最大值,max2 是次大值
		for(int j=1;j<=n;j++)
			if(a[i][j]>max1) max2=max1,max1=a[i][j]; //此时两个值一起变
			else if(a[i][j]>max2) max2=a[i][j];      //只改变次大值
		ans=max(ans,max2);	
	} printf("1\n%d\n",ans);
	return 0;
}

洛谷 P1199 三国游戏 题解

原文:https://www.cnblogs.com/bifanwen/p/12546898.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!