HDOJ、田忌赛马问题的思路以及C/C++实现,可AC

问题描述:
Wang Haiyang is a strong and optimistic Chinese youngster. Although born and brought up in the northern inland city Harbin, he has deep love and yearns for the boundless oceans. After graduation, he came to a coastal city and got a job in a marine transportation company. There, he held a position as a navigator in a freighter and began his new life.

The cargo vessel, Wang Haiyang worked on, sails among 6 ports between which exist 9 routes. At the first sight of his navigation chart, the 6 ports and 9 routes on it reminded him of Graph Theory that he studied in class at university. In the way that Leonhard Euler solved The Seven Bridges of Knoigsberg, Wang Haiyang regarded the navigation chart as a graph of Graph Theory. He considered the 6 ports as 6 nodes and 9 routes as 9 edges of the graph. The graph is illustrated as below.

According to Graph Theory, the number of edges related to a node is defined as Degree number of this node.

Wang Haiyang looked at the graph and thought, If arranged, the Degree numbers of all nodes of graph G can form such a sequence: 4, 4, 3,3,2,2, which is called the degree sequence of the graph. Of course, the degree sequence of any simple graph (according to Graph Theory, a graph without any parallel edge or ring is a simple graph) is a non-negative integer sequence?

Wang Haiyang is a thoughtful person and tends to think deeply over any scientific problem that grabs his interest. So as usual, he also gave this problem further thought, As we know, any a simple graph always corresponds with a non-negative integer sequence. But whether a non-negative integer sequence always corresponds with the degree sequence of a simple graph? That is, if given a non-negative integer sequence, are we sure that we can draw a simple graph according to it.?

Let’s put forward such a definition: provided that a non-negative integer sequence is the degree sequence of a graph without any parallel edge or ring, that is, a simple graph, the sequence is draw-possible, otherwise, non-draw-possible. Now the problem faced with Wang Haiyang is how to test whether a non-negative integer sequence is draw-possible or not. Since Wang Haiyang hasn’t studied Algorithm Design course, it is difficult for him to solve such a problem. Can you help him?

Input

The first line of input contains an integer T, indicates the number of test cases. In each case, there are n+1 numbers; first is an integer n (n<1000), which indicates there are n integers in the sequence; then follow n integers, which indicate the numbers of the degree sequence.

Output

For each case, the answer should be "yes"or “no” indicating this case is “draw-possible” or “non-draw-possible”

Sample Input

2
6 4 4 3 3 2 2
4 2 1 1 1

Sample Output

yes
no

基本思路

田忌赛马问题的核心在于“略胜一筹”的概念(贪心算法)。我们始终优先考虑略胜一筹的情况,这样可以尽可能多得赢嘛。所以我们将田忌与齐王的马按照从优到劣进行排序。比赛以下情况:
(需要注意的事,每次参赛的只有最优的马或者最劣的马,参赛完后,最优或者最劣的马就会被消耗掉,也就是从田忌以及齐王的数组中剔除,那么双方剩下的马仍然是一个有着最优和最劣马的相等的数组)

  1. 只要田忌的最优马略胜齐王的最优马一筹,那么我们就比赛,赏金加200。
  2. 如果田忌的最优马败于齐王的最优马,那么我们就把田忌的最劣马献祭掉,消耗掉齐王最优马。赏金减200.
  3. 如果双方最优马实力相当,我们先比较一下最劣马,情况和最优马类似:
    1):如果此时田忌最劣马略胜给齐王最劣马,那么比赛,赏金加200.
    2):如果此时田忌最劣马略输给齐王最劣马,那么同理,我们将最劣马献祭掉,用来消耗齐王的最优马。赏金减200.
    3):如果此时双方最劣马能力也相等,那么我们就要分以下2个情况谈论了:
    情况1:如果此时田忌最劣的马和田忌的最优的马质量是一样的。如代码的第二个测试数据一样。那么就说明田忌所剩的所有马还有齐王的所有马,质量通通是一样的。那么我们也就没有比较的必要了,全是平局。
    情况2:如果此时田忌最劣的马比田忌最优的马差,可此时田忌最劣的马与齐王最劣的马质量是一样的,意味着我这匹马没有任何胜利的可能,那么我就将其贡献最大化,将他与齐王最优马比赛,消耗掉齐王最好马。赏金-200。但是保证了我们能多赢一把,我们最好的马比他最差的马好呀。(此处如果有疑问,可以自己拿数据去尝试尝试,这样做最差的结果就是一胜一负,和两个平局结果一样,不会亏的!)

用到函数:

首先我们需要排序,但是我们用的数组又需要能够动态地删除不要的元素。vector是一个不错的选择,大家可以学习一下。(注意删除数组的第一个元素是vec.erase(vec.begin()),而删除最后一个元素是vec.pop_back(),不要写成vec.erase(vec.end())。我第一次用的时候这个错误犯了无数次。
用 sort排序是一个好东西,大家一定掌握。

代码如下

#include<bits/stdc++.h>
using namespace std;
bool cmpy(int a,int b)    //将马匹从优到劣排序
{
	return a>b;
}
int cmpx(int a)   //当最好马平局,最差马平局时,如果最好马和最差马实力不相等,那么让田忌最差马和齐王最好马比较。 
{
	if(a>0) return 1;
	if(a<0) return (-1);
	if(a==0) return 0;
}
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF&&n!=0)
	{
		int i,tianji[1000],guowang[1000];
		for(i=0;i<n;i++) scanf("%d",&tianji[i]);   //输入田忌和齐王的马。
		for(i=0;i<n;i++) scanf("%d",&guowang[i]);
		vector<int> wang(guowang,guowang+n);   //将田忌和齐王的马装进vector容器当中(也就是一个可以动态删减元素的数组)。
		vector<int> tian(tianji,tianji+n);
		sort(wang.begin(),wang.end(),cmpy);     //排序
		sort(tian.begin(),tian.end(),cmpy);
		int sum=0,flag=0;     //用sum记录赏金,赢了+1,输了-1,平局不变,用flag记录比赛的次数,当次数达到n时,说明比完了。
		while(flag!=n)    
		{
			if(tian.front()>wang.front())   //田忌的最优马比齐王最快的还快  赢一场。
			{
				sum++;flag++;
				tian.erase(tian.begin());
				wang.erase(wang.begin());
			}
			 if((tian.front())<(wang.front()))  //田忌的最优马比齐王最快的还慢  献祭最慢的,输一场。
			{
				sum--;flag++;
				tian.pop_back();
				wang.erase(wang.begin());
			}
			if(tian.front()==wang.front()) //田忌的最优马与齐王最快的相等 
			{
				if(tian.back()>wang.back())    //田忌的最劣马比齐王最劣还快  赢一场
				{
					sum++;flag++;
					tian.pop_back();
					wang.pop_back();
				}
				if(tian.back()<wang.back())   //田忌的最劣马比齐王最劣还慢  ,献祭最劣的,输一场。
				{
					sum--;
					flag++;
					tian.pop_back();
					wang.erase(wang.begin());
				}
				if(tian.back()==wang.back())      //如果双方最劣马也相等
				{
					if(tian.back()!=tian.front())      //如果田忌最劣马和最优马实力不一样,说明还需要比赛。用田忌最劣马和齐王最优马比赛,输一场。
					{
						sum--;    
						flag++;
						tian.pop_back();
						wang.erase(wang.begin());
					}
					if(tian.back()==tian.front())   //如果田忌所有马质量都一样,说明没有比赛的必要了
						break;
				}
			}
		}
		printf("%d\n",sum*200);   //输出赏金
	}
}

欢迎大家交流,互相学习啦!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值