目录

Tian Ji -- The Horse Racing

要求:

描述:

输入 :

输出:

样例输入:

样例输出:

问题分析:

情况一:

情况二:

情况三:

最终代码:

总结:

其他思路:


Tian Ji -- The Horse Racing

要求:

总时间限制: 5000ms

内存限制: 65536kB

描述:

Here is a famous story in Chinese history.

That was about 2300 years ago. General Tian Ji was a high official in the country Qi. He likes to play horse racing with the king and others.

Both of Tian and the king have three horses in different classes, namely, regular, plus, and super. The rule is to have three rounds in a match; each of the horses must be used in one round. The winner of a single round takes two hundred silver dollars from the loser.

Being the most powerful man in the country, the king has so nice horses that in each class his horse is better than Tian's. As a result, each time the king takes six hundred silver dollars from Tian.

Tian Ji was not happy about that, until he met Sun Bin, one of the most famous generals in Chinese history. Using a little trick due to Sun, Tian Ji brought home two hundred silver dollars and such a grace in the next match.

It was a rather simple trick. Using his regular class horse race against the super class from the king, they will certainly lose that round. But then his plus beat the king's regular, and his super beat the king's plus. What a simple trick. And how do you think of Tian Ji, the high ranked official in China?

Were Tian Ji lives in nowadays, he will certainly laugh at himself. Even more, were he sitting in the ACM contest right now, he may discover that the horse racing problem can be simply viewed as finding the maximum matching in a bipartite graph. Draw Tian's horses on one side, and the king's horses on the other. Whenever one of Tian's horses can beat one from the king, we draw an edge between them, meaning we wish to establish this pair. Then, the problem of winning as many rounds as possible is just to find the maximum matching in this graph. If there are ties, the problem becomes more complicated, he needs to assign weights 0, 1, or -1 to all the possible edges, and find a maximum weighted perfect matching...

However, the horse racing problem is a very special case of bipartite matching. The graph is decided by the speed of the horses -- a vertex of higher speed always beat a vertex of lower speed. In this case, the weighted bipartite matching algorithm is a too advanced tool to deal with the problem.

In this problem, you are asked to write a program to solve this special case of matching problem.

输入 :

The input consists of up to 50 test cases. Each case starts with a positive integer n ( n<=1000) on the first line, which is the number of horses on each side. The next n integers on the second line are the speeds of Tian's horses. Then the next n integers on the third line are the speeds of the king's horses. The input ends with a line that has a single `0' after the last test case.

输出:

For each input case, output a line containing a single number, which is the maximum money Tian Ji will get, in silver dollars.

样例输入:

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

样例输出:

200
0
0

问题分析:

这是众所周知的田忌赛马问题,我们先来理一下这个英文题面。田忌和齐王赛马,约定谁赢一局 就会从对手那里赢取200银元. 如果双方平局,则钱数不会发生变化。那么对于给定的马速序列,我们希望知道田忌最多能够赢多少银元,或者说最少会输掉多少银元。

输入有若干组,以0结束;每一组中第一行n代表双方各有多少匹马,接下来的两行分别代表田忌的马的速度与齐王的马的速度,(注意:虽然样例是从大到小给出,但测试时数据并不一定按照从大到小给出)最后输出田忌所赢钱数就可以了。

while(scanf("%d",&n)&&n!=0){//输入部分cin.get();//因为用的是scarf,所以需要读掉每行最后的回车int Tian[n];int King[n];for(int i=0;i<n;i++){scanf("%d",&Tian[i]);}cin.get();for(int i=0;i<n;i++){scanf("%d",&King[i]);}cin.get();
}

一个自然的思路是通过搜索(枚举),遍历所有可能,从而找到收益最大的值。但我们注意到双方的马匹数是0~1000,这个数据还是非常大的,因为遍历所有可能的时间复杂度是O(n!),也就是最多需要进行1000!次枚举,这个时间是我们不能忍受的,即使本题时间要求是5000ms。

所以我们希望找到一些好的算法(贪心),结合历史上的田忌赛马事件,我们可以简单地得出一个粗糙的“结论”:如果我们用自己的劣马耗掉对方的良马,我方的优势就会扩大。那么基于这样一个“结论”,我们可以对这个想法进行精细化讨论和实现。

首先我们需要对双方的马进行排序,以便我们后续查找对应的马。(这里用到了lambda表达式进行从大到小排序,如果不清楚的话,自己写一个比较函数或者默认从小到大排序也可以)

sort(King,King+n,[](int a,int b){return a>b;});//对于传入的int型a和b,返回a>b的bool值
sort(Tian,Tian+n,[](int a,int b){return a>b;});

情况一:

所以我们就来考虑田忌方最差的马,我们希望可以最大化利用这匹马,那么当我们这匹马连对面最差的马都不如的话,直接用它来消耗对面最好的马(这匹马不管面对谁,结果都为负,所以消耗掉对面最好的马就是收益最好的结果)

田忌赛马历史故事告诉我们的只有以上规则,但我们可以看到这个规则很不完善:我们仍需分类讨论,当我们的最劣马等于对方最劣马时以及优于对方最劣马的情况。

情况二:

如果我方的最劣马优于对方的最劣马,若此时我们仍用此马来消耗对面最优马,这个情况是不好的,因为我们总能找到一个至少不差并且可能更优的局面:

假设我们现在不考虑己方最差马N和对方最优马P后得到的最大收益是K,那么用最差马消耗对面最优马的最佳收益就是(K+(N与P比赛结果))*200,那么在该局面下,我方总有一匹马M和对方最差马Q比赛并且获胜(M>=N>Q),那么当我们用N来和Q比,用M来跟P比,其他比赛不变,我们此时的收益为((K-1)+1+(M与P比赛结果))*200,由于M>=N,所以这个结果至少不会差于上一个局面。

所以如果我方的最劣马优于对方的最劣马,我们总是用己方最劣马来和对方最劣马比赛并获胜。

情况三:

如果我方的最劣马刚好和对方最劣马相当时,我们怎么处理?

考虑这两组数据:

2
20 10
15 10
2
15 10
20 10

对于第一组,我们不能用己方最差换对面最好,这样做(一输一胜)的收益是0,小于最大收益(一平一胜)200;但是对于第二组,我们必须用己方最差换对面最好,(一输一胜)收益为0,大于(一平一输)收益为-200.

所以从上述的例子中我们可以发现此时需要针对最优马再进行分类讨论,如果我方最优马比对方更好,直接最优马先赢下这一局,否则就用最劣马去换掉对面最优的。(证明方式类似上面)

最终代码:

所以在上面的分类讨论中,我们已经把情况讨论齐全。

#include<iostream>
#include<algorithm>
using namespace std;
int main(){int n;while(scanf("%d",&n)&&n!=0){//输入部分cin.get();int *Tian=new int[n];//田忌int *King=new int[n];//齐王for(int i=0;i<n;i++){scanf("%d",&Tian[i]);}cin.get();sort(Tian,Tian+n,[](int a,int b){return a>b;});for(int i=0;i<n;i++){scanf("%d",&King[i]);}cin.get();sort(King,King+n,[](int a,int b){return a>b;});//算法部分int Money=0;int KingLast=n-1;int KingFirst=0;int TianFirst=0;for(int TianLast=n-1;TianLast>=TianFirst;){if(Tian[TianLast]<King[KingLast]){//情况一Money--;KingFirst++;TianLast--;}else if(Tian[TianLast]>King[KingLast]){//情况二KingLast--;Money++;TianLast--;}else{//情况三if(Tian[TianFirst]<=King[KingFirst]){//如果最优没有对面好,用最后去换if(Tian[TianLast]<King[KingFirst]) Money--;KingFirst++;TianLast--;}else{//如果己方最优马比对方最优马好Money++;KingFirst++;TianFirst++;}}}printf("%d\n",Money*200);//释放内存delete []Tian;delete []King;}
}

总结:

一道经典的贪心算法,最难的就是对各种情况的讨论以及证明,一定切记避免想当然,不然很容易漏掉一些情况。希望这篇文章对您有所帮助。最后求赞求关注

OpenJudge Tian Ji -- The Horse Racing相关推荐

  1. hdu 1052 Tian Ji -- The Horse Racing

    Tian Ji -- The Horse Racing Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Jav ...

  2. 贪心法田忌赛马问题Java代码,hdoj 1052 Tian Ji - The Horse Racing【田忌赛马】 【贪心】...

    hdoj 1052 Tian Ji -- The Horse Racing[田忌赛马] [贪心] 思路:先按从小到大排序, 然后从最快的开始比(假设i, j 是最慢的一端, flag1, flag2是 ...

  3. hdu-1052 Tian Ji -- The Horse Racing

    HOT!!! 欢迎参加"金山西山居-2013创意游戏程序挑战赛"! Tian Ji -- The Horse Racing Time Limit: 2000/1000 MS (Ja ...

  4. Tian Ji -- The Horse Racing(田忌赛马)/贪心算法

    Tian Ji – The Horse Racing(田忌赛马) 田忌赛马的故事 (可以直接看题) Here is a famous story in Chinese history. "T ...

  5. Tian Ji -- The Horse Racing(贪心+STL)

    Problem:Tian Ji – The Horse Racing Description: Here is a famous story in Chinese history. "Tha ...

  6. 贪心算法 003:Tian Ji -- The Horse Racing

    003:Tian Ji – The Horse Racing 总时间限制: 5000ms 内存限制: 65536kB 描述 Here is a famous story in Chinese hist ...

  7. 杭电1042c语言循环,HDU杭电1052 Tian Ji - The Horse Racing答题报告

    HDU杭电1052 Tian Ji -- The Horse Racing解题报告 本人第一次写博客,希望各位大神多多指导与包涵,不足的地方还请指出,新手在此谢过啦!!! 题目描述: Time Lim ...

  8. LA 3266 Tian Ji -- The Horse Racing

    题目 LA 3266 Tian Ji – The Horse Racing 题解 这神奇的贪心我是并没有想出来,只会做没有平局的情况,感觉自己太傻比,不知道怎么冲省选了.找的是这篇题解:http:// ...

  9. Tian Ji -- The Horse Racing 贪心算法

    Problem Description Here is a famous story in Chinese history. "That was about 2300 years ago. ...

最新文章

  1. acu风格是什么意思_“高街风格”是什么意思?
  2. Form_Form Builder Export导出为Excel(案例)
  3. java ee ide 假死_Eclipse编辑jsp、js文件时卡死现象的解决办法汇总
  4. [剑指offer]面试题8:旋转数组的最小数字
  5. java list 比较相同的元素_java list 比较相同的元素 | 学步园
  6. python之cookbook-day03
  7. C语言实现简单的单例模式
  8. 在ubuntu系统下cocos2dx移植到android平台
  9. gulp-API介绍
  10. Spring 的 ApplicationEvent and ApplicationListener
  11. js学习笔记(新手向)
  12. windows8无法播放优酷土豆视频解决方法
  13. web前端 html+css+javascript网页设计实例 家乡网站制作
  14. 三菱MDS-D-SVJ3-10/20/10NA/20NA伺服驱动器
  15. MAC wps中选中的页面和缩放打印
  16. Android 播放本地 ts 格式视频
  17. Source(拉电流) Sink(灌电流)详解
  18. mysql如何提高查询效率_MySQL调优系列——如何提高MySQL的查询效率
  19. vc707(virtex7)FLASH下载实验
  20. Hash算法及数字签名【六】

热门文章

  1. 三部曲简史mobi_尤瓦尔.赫拉利简史三部曲(电子书)
  2. XSCTF联合招新【真是阳间题】(MSIC+Crypto)
  3. Unity+Android 打开安卓文件管理器,并拿到文件的真实路径
  4. python导出数据到excel文件_Python笔记:把数据导出到Excel文件上
  5. vba 定义类_类模块的定义及设计
  6. CF 1680 E. Moving Chips dp 2000
  7. 图书借阅管理系统的设计与实现(Java+SSH+MySQL)
  8. 本科毕业论文检测 有没有自己可以检测的系统,怎么进去检测?
  9. 嵌入式linux学习路线,嵌入式开发视频教程
  10. Linux 日历和计算器命令