题目描述
题目来源 BUPT ACM 洛谷P1650田忌赛马和这个类似
Problem Description
“田忌赛马”是中国历史上一个著名的故事。
大约2300年前,齐国大将田忌喜欢和国王赛马,并且约定:每赢一场,对方就要付200元。
假设已知田忌和国王的各自马匹的速度都不相同,请计算田忌最好的结果是什么。
Input
输入包含多组测试样例。
每组样例的第一行是一个整数n(n <= 1000),表示田忌和国王各自参赛的马匹数量。
接下来一行的n个整数表示田忌的马的速度,再接下来一行的n个整数表示国王的马的速度。
n为0时,表示输入数据的结束。
Output
每组数据输出一行,表示田忌最多能够赢得的金额。
输入样例
3
92 83 71
95 87 74
2
20 19
22 18
0
输出样例
200
0
思路分析
从小故事中我们可以领会到,田忌出马的策略其实就是贪心的策略,让马能赢就赢,做到“物尽其用”;(最慢的马)怎么也赢不了的时候,就“殊死一搏”,去挑战对方最快的马(注意这个时候挑战不一定输,也会有平局的现象出现),达到贪心中的利益最大化。
策略
1. 如果田忌最快的马比齐王最快的马快,则两者比(如果不这样可能会输);
2. 如果田忌最快的马比齐王最快的马慢,则拿田忌最慢的马与齐王最快的马比
(齐王拿出最快的马后,田忌怎么样都得输,不妨拿最慢的马比,让损失最小);
3. 如果田忌最快的马与齐王最快的马一样快,则比较双方最慢的马:
如果田忌最慢的马比齐王最慢的马快,则两者比
其他情况,拿田忌最慢的马与齐王最快的马比(这匹马无论如何都赢不了,不如与对方最快的马“同归于尽”)
AC Code
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;
int a[1005],b[1005];
int main(){
int n;
cin>>n;
while(n!=0){
int sum=0;
for(int i=1;i<=n;i++)
cin>>a[i]; //田忌
for(int i=1;i<=n;i++)
cin>>b[i]; //齐王
sort(a+1,a+1+n); //由慢到快排序
sort(b+1,b+1+n);
int left_a=1,left_b=1; //左指针指向较慢的一端
int right_a=n,right_b=n; //右指针指向较快的一端
for(int i=1;i<=n;i++){
if(a[right_a]>b[right_b]){ //田忌最快的马更快
sum+=200;
right_a--;
right_b--;
}else if(a[right_a]<b[right_b]){ //齐王最快的马更快
sum-=200;
left_a++;
right_b--;
}else{ //最快的马一样快,比较最慢的马
if(a[left_a]>b[left_b]){ //田忌最慢的马更快
sum+=200;
left_a++;
left_b++;
}else{ //最慢的马怎么也赢不了(输或平),直接挑战至尊强者——最快的马
if(a[left_a]<b[right_b]) //如果挑战平局的话,就不用掏钱了
sum-=200; //(双方都只剩下一匹马,最慢的和最快的是同一个)
left_a++;
right_b--;
}
}
}
cout<<sum<<endl;
cin>>n;
}
system("pause");
return 0;
}