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

这是一个关于中国历史上的故事,讲述了田忌如何在赛马比赛中使用策略赢得比赛。问题转化为寻找二分图中的最大匹配,特别情况下简化为特定的匹配问题。输入包含两组马的速度,目标是最大化田忌赢得的钱数。解题思路涉及马的速度比较和不同情况的分析。
摘要由CSDN通过智能技术生成

003: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

思路:
tianji的马从小到大排序——国王的马从小到大排序
该题难点在于要分析出所有情况

小马的比较
(1)当T小马大于K小马时——钱++,比较两边第二个小马;
(2)当T小马小于K小马时——必输,不如用小马碰大马,钱–;
(3)当T小马与K小马相等时——需要先比较大马
因为:
可能小马相同,Tian的大马全部大于King的大马,这时无需让小马碰大马,徒增败绩,让小马直接碰掉小马就行了

大马的比较
(1)当T大马大于K大马时——钱++,比较两边第二大马;
(2)当T大马小于K大马时——必输,让T小马碰K大马,钱–;
(3)当T大马等于K大马且T小马=K小马时——还是小马碰大马
如果小马小于对方大马,则钱–,不然钱不变;

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

int n;
int Tian[1010];
int King[1010];
int Win;
int Lose;
int Thead;
int Ttail;
int Ktail; 
int Khead;

int main(){
	freopen("321.txt","r",stdin);
	while(cin>>n){
	if(n==0) break;
	for (int i =0;i<n;i++){
		cin>>Tian[i];
	}
	for (int i =0;i<n;i++){
		cin>>King[i];
	}
	sort(Tian,Tian+n);
	sort(King,King+n);

	Thead=0;
	Ttail=n-1;
	Khead=0;
	Ktail=n-1;
	Win=0;
	Lose=0;
		while(Thead<=Ttail){              //循环整个tian 
			if(Tian[Thead]>King[Khead]){
				Win++;
				Khead++;
				Thead++;         //比得过小碰小 
			}
			else if(Tian[Thead]<King[Khead]){
				Lose++;
				Thead++;         //比不过小碰大 
				Ktail--;
			}
			else{
			if(Thead==Ttail)  break;                //最小值相同
			if(Tian[Ttail]>King[Ktail]){     //比得过大碰大 
				Win++;
				Ttail--;
				Ktail--;
			}
			//最大值也相等就碰掉
			else{
      //比不过小碰大 
      			if(Tian[Thead]<King[Ktail])    //最小值比king最大值小时 
							Lose++;
				Thead++;		//如果头尾都相等——用小的把大的给碰了; 
				Ktail--;
		}
			}
}		
		cout<<(Win-Lose)*200<<endl;
}
} 

一个错误:

1)认为最快的两个马一样快,就碰掉
2) 在最快马相同时,认为最慢的两个马一样快,就碰掉 ****。其实还是应该拿最慢马去和对方最快马比。考虑两个序列完全相同的情况
3) 没考虑到最后剩下两个马一样快的情况
4) 在最快马等速时,认为自己的尾马一定比对方的头马慢

问题的关键是,头马一样快,且尾马也一样快,则用自己尾马对对方头马。证明:替换法。

假设最优法是两个尾马兑掉,在这种情况下的最佳做法里面,对方的头马a,对的是我的马x
那么我可以维持其它对局不变,用我的尾马 z对a, x对对方的尾马b (z=b)
若a>x ,则变换后,a还是赢的,但我方原来输掉的x >= b,变换后的结果不会更差
若a=x, 则变换后, a对z, x 对b。
若a>z,则 x > b (因z=x) ,还是扯平,没有变得更差
若a = z,则x=b,还是扯平,也没有变得更差

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值