思路:贪心+分类讨论
链接:https://ac.nowcoder.com/acm/problem/235246
来源:牛客网

题目描述

 我国历史上有个著名的故事: 那是在2300年以前。齐国的大将军田忌喜欢赛马。他经常和齐王赛马。他和齐王都有三匹马:常规马,上级马,超级马。一共赛三局,每局的胜者可以从负者这里取得200银币。每匹马只能用一次。齐王的马好,同等级的马,齐王的总是比田忌的要好一点。于是每次和齐王赛马,田忌总会输600银币。
 田忌很沮丧,直到他遇到了著名的军师――孙膑。田忌采用了孙膑的计策之后,三场比赛下来,轻松而优雅地赢了齐王200银币。这实在是个很简单的计策。由于齐王总是先出最好的马,再出次好的,所以田忌用常规马对齐王的超级马,用自己的超级马对齐王的上级马,用自己的上级马对齐王的常规马,以两胜一负的战绩赢得200银币。实在很简单。 
如果不止三匹马怎么办?现在,就请你设计一个简单的算法解决这个问题。

输入描述:

		
第一行一个整数n,表示他们各有几匹马(两人拥有的马的数目相同)。
第二行n个整数,每个整数都代表田忌的某匹马的速度值(0≤速度值≤100)。第三行n个整数,描述齐王的马的速度值。两马相遇,根据速度值的大小就可以知道哪匹马会胜出。如果速度值相同,则和局,谁也不拿钱。

输出描述:

仅一行,一个整数,表示田忌最大能得到多少银币。仅一行,一个整数,表示田忌最大能得到多少银币。

题型:

贪心+分类讨论

思路:

设田忌为A,齐王为B
先对于A,B的马进行排序(升序/降序均可)
然后考虑分类讨论
先分三种情况(注意,两匹马用完就扔)
1.A的最快的马>B的最快的马:直接用A的最的马和B的最的马比就行,+200
2.A的最快的马<B的最快的马:反正赢不了,直接用A的最的马和B的最的马比就行,-200
3.A的最快的马=B的最快的马:这里需要再次分类讨论,因为不管当前是直接用A的最快的马和B的最快的马比,还是直接用A的最慢的马和B的最快的马比,都有可能会出错
(举个例子:A:1,2,3  B:1,2,3  和  A:2,3  B:1,3,会发现两者一个需要A的最慢的马和B的最快的马比,另一个需要A的最快的马和B的最快的马比
所以,对于第三种情况,再次进行分类讨论
3.1.A的最慢的马>B的最慢的马:那就先不看快的马了,200在眼前,直接用A的最的马和B的最的马比就行,+200
3.2.A的最慢的马<B的最慢的马:最慢的马也-200,最快的马也-200,那直接用A的最的马和B的最的马比就行,至于是否-200,要看A的最的马和B的最的马的速度,相等就-0,不相等就-200
这样就完成了

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+200;
int a[N],b[N],ans=0;
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&b[i]);
	}
	sort(a+1,a+1+n);
	sort(b+1,b+1+n);
	int al=1,ar=n,bl=1,br=n;
	for(int i=1;i<=n;i++){
		if(a[ar]>b[br]){
			ans+=200,ar--,br--;
		}else if(a[ar]<b[br]){
			ans-=200,al++,br--;
		}else{
			if(a[al]>b[bl]){
				ans+=200,al++,bl++;
			}else{
				if(a[al]<b[br]) ans-=200;
				al++,br--;
			}
		}
	}
	printf("%d\n",ans);
	return 0;
}
(P.S.:这题用区间dp也可以做,但是如果数据范围变成1e6,1e7这种,那么区间dp是无法通过的,所以个人感觉这种贪心+分类讨论的方法才是田忌赛马的正解)