题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=1052
开始的时候用排序,然后直接运算,也就是类似于遍历的形式的,但是肯定不对,又用下面代码的形式,按照模拟的形式写的话,又因为最大值且最小值相等时,直接用最小值比较,产生了1 2 3 和1 2 3 的错误,最后看了别人的代码,才弄得差不多了
证明和详解(转载)
题目大意:田忌和国王赛马,给出马的数量n,然后是田忌的n匹马,国王的n匹马。问田忌最多可以赢得多少比赛(一场200块)。
这道题目以前看过,但是没有弄出来,思路是:田忌的最快的马比国王最快的马快,就用田忌最快的马跟国王最快的马比;如果田忌最快的马比国王最快的马慢,就用田忌最慢的马比。
因为只是知道要这样,但对于其他的情况,根本弄不明白要怎么比法,当马的速度一样快的时候,就
因为比赛的时候,是国王先出马,然后田忌再出,田忌有主动权上的优势。
先对田忌和国王的马进行排序。
贪心的策略:
一、当田忌最快的马比国王最快的马快时,用田忌最快的马赢国王最快的马。
二、当田忌最快的马比国王最快的马慢时,用田忌最慢的马输给国王最快的马。
三、当田忌最快的马跟国王最快的马一样快时,分情况。
证明一、:假设现在国王最快的马是K,田忌最快的马是T,如果存在一种更优的比赛策略,让T的对手不是K,而使得田忌赢更多的钱的话,那么设此时K的对手是t,T的对手是k:( T>K &&T>t && K>k)
1、若t>K,则有T>k,t>K。这个结果和T>K,t>k是相同的。
2、若k<t≤K,则有T>k,t≤K。这个结果不如T>K,t>k来得优秀。
3、若t≤k≤K,则有T>k,t≤K。这个结果和T>K,t≤k是相同的。
由此可知,交换各自对手后,一定不会使得结果变劣,那么假设是不成立的。
得证!!
证明二、:因为田忌最快的马比国王最快的马慢,所以田忌所有的马都比国王最快的马慢,也就是说此时田忌的所有马都赢不了国王的马,而出于贪心的思想,应该保留相比之下更快的马,因此用最慢的马去输一定不会比用别的马去输来得劣。
得证!!
其实上面这两个很容易就想得到,最难的是相等的时候。因为不可以直接让田忌最快的马跟国王最快的马打平,或者直接用最慢的马去输给国王最快的马。(存在反例)
1、如果选择全部打平,那么对于田忌 1 2 3 4,国王 1 2 3 4 ,这组数据,田忌什么黄金也得不到。但是如果选择 1->4, 4->3, 3->2, 2->1田忌可以得到400两黄金。 (大雄想的)
2、如果选择用最慢的马输掉比赛的话,对于田忌
所以:对于情况三,我们应该从最慢的马开始考虑了
1、当田忌最慢的马比国王最慢的马快,那么用田忌最慢的马赢国王最慢的马
2、当田忌最慢的马比国王最慢的马慢,那么用田忌最慢的马输给国王最快的马
3、当田忌最慢的马跟国王最慢的马相等的时候,用田忌最慢的马跟国王最快的马比
证明1、:假设现在国王最慢的马是K,田忌最慢的马是T,如果存在一种更优的比赛策略,让T的对手不是K,而使得田忌赢更多的钱的话,那么设此时K的对手是t,T的对手是k:( T>K &&t>T && k>K)
1、若T>k,则有T>k,t>K。这个结果和T>K,t>k是相同的。
2、若T<k≤t,则有T<k,t>K。。这个结果不如T>K,t>k来得优秀。
3、若K≤t≤k,则有T>k,t≤K。这个结果和T>K,t≤k是相同的.
由此可知,交换各自对手后,一定不会使得结果变劣,那么假设是不成立的。
得证!!
证明2、:因为田忌最慢的马比国王最慢的马慢,所以田忌最慢的马都比国王所有的马慢,也就是说此时田忌最慢的马赢不了国王的任何一匹马,而出于贪心的思想,应该去掉国王最快的马,因此输给国王最快的马一定不会比输给其他的马来得劣。
得证!!
证明3、:因为田忌最快T和最慢t的马与国王最快K和最慢k的马都相等,如果用最快的马跟国王最快的马比,最慢的马和国王最慢的马比,那么田忌什么收获也没有。此时是T->K, t->k,其实这个时候我们可以换个角度想,上面这种情况跟T->k, t->k,没有什么区别,都是双方少了最快和最慢的马。但是从证明二可知,我们必须让最慢的马输给国王最快的马,而在田忌的马中找任何一匹比最慢的马快一点的马去赢国王最慢的马都行,这样田忌在同样一胜一负的情况下,保留了跑得更快的马,会比把最快的马拿去比赛来得更优些。
得证!!
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=1005; int tj[maxn], qw[maxn]; int main() { int n, i, sum, max1, max2, min1, min2, cnt; while(~scanf("%d", &n) && n) { for(i=0; i<n; i++) scanf("%d", &tj[i]); for(i=0; i<n; i++) scanf("%d", &qw[i]); sort(tj, tj+n); sort(qw, qw+n); sum=0, cnt=0; max1=max2=n-1; min1=min2=0; while((cnt++)<n) { if(tj[max1]>qw[max2]) sum += 200, max1--,max2--; else if(tj[max1]<qw[max2]) sum -= 200, min1++,max2--; else { if(tj[min1]>qw[min2])// sum += 200, min1++, min2++; else{//田忌的慢马<=国王的慢马 if(tj[min1]<qw[max2]) sum -= 200; min1++,max2--; } } } printf("%d ", sum); } return 0; }