求解田忌赛马问题
问题
问题描述
两千多年前的战国时期,齐威王与大将田忌赛马。双方约定每人各出 300 匹马,并且在上、中、下 3 个等级中各选一匹进行比赛,由于齐威王每个等级的马都比田忌的马略强,比赛的结果可想而知。现在双方各 n 匹马,依次派出一匹马进行比赛,每一轮获胜的一方将从输的一方得到 200 银币,平局则不用出钱,田忌已知所有马的速度值并可以安排出场顺序,问他如何安排比赛获得的银币最多?
Tip: 本题为单组输入
输入描述

输出描述
每个测试用例输出一行,表示田忌获得的最多银币数。
样例输入
3
92 83 71
95 87 74
样例输出
200
思考
ppt复读机
贪心算法
先分别把田忌和齐威王的马按速度由低到高排序。
可以分为以下几种情况:
1.田忌最快的马比齐威王最快的马慢,此时用田忌最慢的马和齐威王最快的马比,失败+1
2.田忌最快的马比齐威王最快的马快,此时用田忌最快的马和齐威王最快的马比,胜利+1
3.田忌最快的马和齐威王最快的马一样快,此时问题继续考虑以下情况
1.田忌最慢的马比齐威王最慢的马快,此时用田忌最慢的马和齐威王最慢的马比,胜利+1
2.田忌最慢的马比齐威王最慢的马慢/一样慢,此时用田忌最慢的马和齐威王最快的马比,如果田忌最慢的马比齐威王最快的马慢,失败+1,否则平局
最初我对3.2的情况不能理解,想不通为什么要加一条如果田忌最慢的马比齐威王最快的马慢,失败+1的判断,既然田忌最快的马和齐威王最快的一样快,那么田忌最慢的马不是理所应当的比齐威王最快的马慢吗?直接失败+1不就欧克了。后来,发现自己忽略了一种情况,那就是如果田忌的马速度都一样,那么此时田忌最慢的马不也和齐威王最快的马速度相同了吗,这是就是平局。
代码
点击查看代码
#include <iostream>
using namespace std;
int competition(int *a, int *b, int s1, int t1, int s2, int t2);
//快速排序
void QuickSort(int a[], int s, int t);
int Partition(int a[], int s, int t);
int main()
{
int n; //马的数量
cin >> n;
int *tianji = new int[n]; //田忌的马的速度
int *qiwei = new int[n]; //齐威王的马的速度
for (int i = 0; i < n; i++)
cin >> tianji[i];
for (int i = 0; i < n; i++)
cin >> qiwei[i];
//为马按马的速度由低到高排序
QuickSort(tianji, 0, n - 1);
QuickSort(qiwei, 0, n - 1);
cout << competition(tianji, qiwei, 0, n - 1, 0, n - 1) << endl;
return 0;
}
// a[...]田忌的马
// b[...]齐威王的马
int competition(int *a, int *b, int s1, int t1, int s2, int t2)
{
int coin = 0; //银币数量
while (s1 <= t1)
{
//田忌最快的马比齐威王最快的马还慢
//用田忌最慢的马和齐威王最快的马比
if (a[t1] < b[t2])
{
coin -= 200; //输了200银币
t2--; //齐威王目前最快的马参加了比赛
s1++; //田忌目前最慢的马参加了比赛
}
//田忌最快的马比齐威王最快的马还慢
//用田忌最快的马和齐威王最快的马比
else if (a[t1] > b[t2])
{
coin += 200; //赢了200银币
t1--; //田忌目前最快的马参加了比赛
t2--; //齐威王目前最快的马参加了比赛
}
//田忌最快的马与齐威王最快的马马速相等
//再分3种情况
else
{
//田忌最慢的马比齐威王最慢的马快
//用田忌最慢的马和齐威王最慢的马比
if (a[s1] > b[s2])
{
coin += 200;
s1++;
s2++;
}
// 田忌最慢的马比齐威王最慢的马慢/相等
else
{
//田忌最慢的马比齐威王最快的马慢
if (a[s1] < b[t2])
coin -= 200;
s1++;
t2--;
}
}
}
return coin;
}
void QuickSort(int a[], int s, int t)
{
//对a[s....t]元素进行递增排序
if (s < t)
{
int i = Partition(a, s, t);
QuickSort(a, s, i - 1);
QuickSort(a, i + 1, t);
}
}
int Partition(int a[], int s, int t)
{
int i = s, j = t;
int temp = a[s]; //用第一个记录作为基准
while (i != j) //从序列两端交替向中间扫描,直到i=j为止
{
while (j > i && a[j] >= temp)
j--; //从右向左扫描,找到第一个小于temp的a[j]
a[i] = a[j];
while (i < j && a[i] <= temp)
i++; //从右向左扫描,找到第一个大于temp的a[i]
a[j] = a[i];
}
a[i] = temp;
return i;
}

浙公网安备 33010602011771号