贪心算法——田忌赛马

304 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情

题目描述:

田忌与齐王赛马,双方各有n匹马参赛,每场比赛赌注为200两黄金,现已知齐王与田忌的每匹马的速度,并且齐王肯定是按马的速度从快到慢出场,现要你写一个程序帮助田忌计算他最好的结果是赢多少两黄金。

说明: 为了简单起见,保证2n匹马的速度均不相同。

输入格式:

输入每组测试数据占3行,第一行是n(n<=1000),表示双方参赛马的数量,第2行n个正整数,表示田忌的马的速度,第3行n个正整数,表示齐王的马的速度.测试数据以“0”结束。

输出格式:

每组测试数据输出一行数据,表示田忌比赛的最好结果是赢多少两黄金。

输入样例:

3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0

输出样例:

200
0
0

代码长度限制   16 KB

时间限制     400 ms

内存限制     64 MB


初看:不好处理
细看:找最优解,贪心算法

思路分析:

vector动态数组记录田忌和齐王的马质量,由于需要有一定的排序来做题,所以直接用vector排序功能

每次循环记录赢得次数

当田忌最慢的马比齐王最慢的马快时

  • 赢得次数加一
  • 然后让田忌与齐王的低位指针+1

当田忌最快的马比齐王最快的马快时

  • 赢得次数加一
  • 田忌和齐王高位指针减一

最后如果田忌最慢的马比齐王最快的马快时

  • 赢得次数减一

最后赢得次数乘以200输出即可

代码如下:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main()
{
	int n;
	vector<int>TJ, QW;
	while (1) {
		int win_cnt = 0, x;
		cin >> n;
		if (n == 0)
			break;
		for (int i = 0; i < n; i++) {
			cin >> x;
			TJ.push_back(x);
		}
		for (int i = 0; i < n; i++) {
			cin >> x;
			QW.push_back(x);
		}
		//sort排序一下
		sort(TJ.begin(), TJ.end());
		sort(QW.begin(), QW.end());
		int T_high = n - 1, Q_high = n - 1;
		int T_low = 0, Q_low = 0;
		while (T_low <= T_high) {
			//当田忌最慢的马比齐王最慢的马快时
			if (TJ[T_low] > QW[Q_low]) {
				win_cnt++;
				T_low++;
				Q_low++;
			}
			//当田忌最快的马比齐王最快的马快时
			else if (TJ[T_high] > QW[Q_high]) {
				win_cnt++;
				T_high--;
				Q_high--;
			}
			else {
				//用田忌最慢的马比齐王最快的马
				if (TJ[T_low] < QW[Q_high])
					win_cnt--;
				//如果平局就直接下一步
				T_low++;
				Q_high--;
			}
		}
		cout << win_cnt * 200 << endl;
		QW.clear();
		TJ.clear();
	}
}

PS:成功解题=理清思路+一定的技巧~