洛谷 P1650 田忌赛马题解
原题目链接:https://www.luogu.com.cn/problem/P1650
思路
需要的是一个贪心算法,这个地方我们只要把贪心的时候把每种分支情况考虑清楚,就可以保证自己做的贪心都是正确的了。
我们先对田忌的马按照速度从大到小排序,齐王的也是。因为田忌可以自由选择顺序,所以这个地方是正确的。
接下来开始贪心
我们的原则从速度快的马开始考虑,如果选择出来的那匹马能赢,就一定要赢,如果不赢,反正我赢不了,就拿烂的马恶心齐王。
1: 如果在剩下的所有马里,如果田忌跑的最快的马,比齐王跑的最块的马还快,那么田忌自然需要让马出场,赢了这把。
2: 如果在剩下的所有马里,如果田忌跑的最快的马,比齐王跑的最块的马要慢,那么这样田忌所有的马绝对没有可能会赢齐王最快的马了,反正都是输,所以这个时候我们只能用田忌最烂的马去把齐王最好的马抵掉。这样一来还能造成一个局面,就是田忌只损失了最烂的一匹马,但是剩余的马都是很优秀的,但是齐王却损失了最好的一匹马,虽然这把输了,但是日后赢回来的可能性是最大的。
3: 如果在剩下的所有马里,如果田忌跑的最快的马,和齐王跑的最快的马一样快,这个时候我们我们考虑最慢的两匹马(为什么突然想到考虑这两匹马,这个我感觉是需要点脑洞的,我也不知道,可能是这样方便贪心吧,毕竟每次都要选择一匹马上场 XD)
4: 如果田忌最慢的马比齐王最慢的马还要块,那么就赢了他,毕竟如果你不赢了,之后就没机会了。
5: 如果田忌最慢的马比齐王最慢的马还要慢,啧啧啧,我看这面相,怕是没戏,所以这匹马直接去和齐王最快的马比。反正横竖赢不了。
6: 最麻烦的一点来了,如果田忌这个时候最慢的马还是和齐王最慢的马一样快,那怎么处理呢?这个时候因为这匹马最多只是平局,那么还是只能和齐王最慢的马比较了
按照这样我们就能至少让每把比赛都能有一个马上场,而且能确保
上场的马要么能赢,要么对整体结果的损失最小
代码
#include <iostream>
#include <algorithm>
using std::cin;
using std::cout;
using std::endl;
using std::sort;
const int N = (int)2e3 + 5;
int a[N]; // 田忌的数据
int b[N]; // 齐王的数据
bool cmp(int a, int b)
{
return a > b;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a, a + n, cmp);
for (int i = 0; i < n; i++)
cin >> b[i];
sort(b, b + n, cmp);
int s1 = 0, e1 = n - 1;
int s2 = 0, e2 = n - 1;
int money = 0;
while (n > 0)
{
if (a[s1] > b[s2])
{
money += 200;
s1++;
s2++;
}
else if (a[s1] < b[s2])
{
money -= 200;
e1--;
s2++;
}
else
{
if (a[e1] > b[e2])
{
money += 200;
e1--;
e2--;
}
else if (a[e1] < b[s2])
{
money -= 200;
e1--;
s2++;
}
else
{
e1--;
e2--;
}
}
n--;
}
cout << money << endl;
return 0;
}