田忌赛马 贪心算法

算法实验课回顾

田忌赛马

问题描述

你一定听说过田忌赛马的故事吧?如果3匹马变成n匹(n<=100),齐王仍然让他的马按照优到劣的顺序初赛,田忌可以按任意顺序选择他的赛马出赛。赢一局,田忌可以得到200两银子;输一局,田忌就要输掉200两银子。已知道国王和田忌的所有马的奔跑速度,并且所有马的奔跑速度均不相同,现已经对两人的马分别从快到慢排好序。请设计一个算法,帮助田忌赢得最多的银子。

要求:

输入:第一行一个整数n,表示双方各有n匹马;

第二行n个整数分别表示田忌的n匹马的速度;

第三行n个整数分别表示齐王的n匹马的速度。

输出:若通过聪明的你精心安排,如果能赢得比赛(赢的次数大于比赛总次数的一半),那么输出“YES”。 否则输出“NO”。并输出一个整数,代表田忌最多能赢多少两黄金。

  1. 如果田忌最快的马比齐王最快的马快,则比之

  2. 如果田忌最快的马比齐王最快的马慢,则用田最慢的马跟齐最快的马比

    // 这是贪心的第一步

  3. 如果田忌最快的马的速度与齐威王最快的马速度相等

    1. 如果田忌最慢的比齐威王最慢的快,则比之

      // 这是贪心的第二步

    2. 如果田忌最慢的比齐威王最慢的慢,田忌慢VS齐王快

    3. 田忌最慢的与齐威王最慢的相等,田忌慢VS齐王快

代码 C++实现

#include <iostream>
#include <cstdlib>
using namespace std;

// 快排
void Quick(int a[], int begin, int end) {
	if (begin >= end)
		return;

	int t = a[begin];
	int i = begin;
	int j = end;

	while (i < j)
	{
		while (i<j && a[j] < t)
			j--;
		a[i] = a[j];
		while (i < j && a[i] >= t)
			i++;
		a[j] = a[i];
	}
	a[i] = t;
	Quick(a, begin, i - 1);
	Quick(a, i + 1, end);
}

// 田忌赛马算法
int tianRac(int Tian[], int King[], int n) {
	int money = 0; // 田忌赢的钱
	int tianh = 0, tiane = n-1, kingh = 0, kinge = n-1;	// 分别标记田忌马队和齐王马队的最快和最慢的马
	// 共有 n 次比赛,每进行一次,就换下一匹马(田姥爷就位,开始赛马秀)
	for (int i = 0; i < n; i++) {
		// 田忌快马比齐王快马快时,那就和他一较高下(赌怪,必赢)
		if (Tian[tianh] > King[kingh]) {
			money += 200;
			tianh++;	// 下一个
			kingh++;	// 下一个
		}
		// 田忌快马比齐王快马慢时,用最慢的马跟他最快的比(埋伏他一手,这匹马不用抢,他死定了,反手一个超级加倍,闷声发大财)
		else if (Tian[tianh] < King[kingh]) {
			money -= 200;
			tiane--;
			kingh++;
		}
		// 田忌的快马和齐王的快马一样快时(他也一样快?不过不用怕,他的马赢不了我)
		else {
			// 田忌的慢马比齐王的慢马快时(很牛逼这个马)
			if (Tian[tiane] > King[kinge]) {
				money += 200;
				tiane--;
				kinge--;
			}
			// 田忌的慢马比齐王的慢马一样快和慢时,就用慢马和他快马比(如果将这个慢马换成快马我的马将绝杀,可惜换不得)
			else {
				money -= 200;
				tiane--;
				kingh++;
			}
		}
	}
	// 返回田忌赢的钱(飞机~)
	return money;
}

int main() {
	int n;	// 比赛双方马的数量
	cout << "公等马几何" << endl;
	cin >> n;
	int* Tian = new int[n];
	int* King = new int[n];

	cout << "将军 马之疾" << endl;
	for (int i = 0; i < n; i++) {
		cin >> *(Tian + i);
	}
	cout << "王 马之疾" << endl;
	for (int i = 0; i < n; i++){
		cin >> *(King + i);
	}

	// 排序,降序排
	Quick(Tian, 0, n-1);
	Quick(King, 0, n - 1);

	// 调用“就算佛祖来了,田姥爷也难输”算法
	int result = tianRac(Tian, King, n);
	if (result > 0) {
		cout << "将军 胜" << endl;
		cout << "赢 " << result << "金" << endl;
	}
	else if (result == 0)
	{
		cout << "和" << endl;
	}
	else {
		cout << "王 胜" << endl;
		cout << "赢 " << -result << "金" << endl;
	}

	return 0;
}

测试数据:

95 92 80 85 98 86 81 83
88 89 97 99 82 85 90 91

80 79 90 95 78 85 68 91
95 92 99 85 98 86 85 96

结果截图:

image-20201215213353644image-20201215213353644

image-20201215213418612image-20201215213418612

ps: 这个算法对田姥爷太难输了…

本文作者:Liwker

本文链接:https://www.cnblogs.com/Liwker/p/14141186.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Liwker  阅读(915)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 灰色と青(翻自 米津玄師) kobasolo,春茶
  2. 2 スパークル nin
  3. 3 愛にできることはまだあるかい(翻自 RADWIMPS) 春茶
  4. 4 夏恋慕 kobasolo,春茶
  5. 5 花に亡霊 ヨルシカ
  6. 6 フラレガイガール(翻自 さユり) 春茶
  7. 7 ふたりごと(翻自 RADWIMPS) 茶泡饭,kobasolo,春茶
  8. 8 Lemon 米津玄師
  9. 9 君と100回目の恋(movie ver.) 葵海 starring miwa
  10. 10 風になる つじあやの
  11. 11 Letter Song ヲタみん
  12. 12 my sweetest one Aimer
  13. 13 Ref:rain Aimer
  14. 14 YELLOW(翻自 神山羊) 麦吉_Maggie
灰色と青(翻自 米津玄師) - kobasolo,春茶
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作曲 : 米津玄師

作词 : 米津玄師

袖丈が覚束ない夏の終わり

明け方の電車に揺られて思い出した

懐かしいあの風景

たくさんの遠回りを繰り返して

同じような街並みがただ通り過ぎた

窓に僕が写ってる

君は今もあの頃みたいにいるのだろうか

ひしゃげて曲がったあの自転車で走り回った

馬鹿ばかしい綱渡り 膝に滲んだ血

今はなんだかひどく虚しい

どれだけ背丈が変わろうとも

変わらない何かがありますように

くだらない面影に励まされ

今も歌う今も歌う今も歌う

···

忙しなく街を走るタクシーに

ぼんやりと背負われたままくしゃみをした

窓の外を眺める

心から震えたあの瞬間に

もう一度出会えたらいいと強く思う

忘れることはないんだ

君は今もあの頃みたいにいるのだろうか

靴を片方茂みに落として探し回った

何があろうと僕らはきっと上手くいくと

無邪気に笑えた 日々を憶えている

どれだけ無様に傷つこうとも

終わらない毎日に花束を

くだらない面影を追いかけて

今も歌う今も歌う今も歌う

朝日が昇る前の欠けた月を

君もどこかで見ているかな

何故か訳もないのに胸が痛くて

滲む顔 霞む色

今更悲しいと叫ぶには

あまりに全てが遅すぎたかな

もう一度初めから歩けるなら

すれ違うように君に会いたい

どれだけ背丈が変わろうとも

変わらない何かがありますように

くだらない面影に励まされ

今も歌う今も歌う今も歌う

朝日が昇る前の欠けた月を

君もどこかで見ているかな

何もないと笑える朝日がきて

始まりは青い色`