HDU 1052 - Tian Ji -- The Horse Racing

 可以说是一道比较难的贪心了

 

贪心方法参考:http://www.cnblogs.com/anderson0/archive/2011/05/07/2039971.html

一、当田忌最快的马比国王最快的马快时,用田忌最快的马赢国王最快的马。 
二、当田忌最快的马比国王最快的马慢时,用田忌最慢的马输给国王最快的马。
三、当田忌最快的马跟国王最快的马一样快时,分情况。

证明一、:假设现在国王最快的马是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、如果选择用最慢的马输掉比赛的话,对于田忌    3 4,国王 1    4 ,这组数据,田忌一胜一负,什么黄金也得不到,但是如果田忌选择 3->1 , 4->4 ,一胜一平,田忌可以得到200两黄金。

所以:对于情况三,我们应该从最慢的马开始考虑了

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,没有什么区别,都是双方少了最快和最慢的马。但是从证明二可知,我们必须让最慢的马输给国王最快的马,而在田忌的马中找任何一匹比最慢的马快一点的马去赢国王最慢的马都行,这样田忌在同样一胜一负的情况下,保留了跑得更快的马,会比把最快的马拿去比赛来得更优些。

得证!!

可以说是讲的非常清晰了。

 

附代码:

tq代表目前田忌小朋友最快的马;ts代表目前田忌小朋友最慢的马;

kq代表目前齐王大朋友最快的马;ks代表目前齐王大朋友最慢的马;

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int tian[1005],king[1005],n,cnt;
 5 int tq,ts,kq,ks;
 6 bool cmp(int a,int b){
 7     return a>b;
 8 }
 9 int main()
10 {
11     while(scanf("%d",&n) && n)
12     {
13         for(int i=1;i<=n;i++) scanf("%d",&tian[i]);
14         for(int i=1;i<=n;i++) scanf("%d",&king[i]);
15         
16         sort(tian+1,tian+n+1,cmp);
17         sort(king+1,king+n+1,cmp);
18         
19         //for(int i=1;i<=n;i++) printf("%d ",tian[i]);printf("\n");
20         //for(int i=1;i<=n;i++) printf("%d ",king[i]);printf("\n");
21         
22         kq=tq=1; ks=ts=n; cnt=0;
23         for(int i=1;i<=n;i++)
24         {
25             if(tian[tq]>king[kq])
26             {
27                 cnt++;
28                 //printf("%d vs %d = %d\n",tq,kq,cnt);
29                 tq++; kq++;
30             }
31             else if(tian[tq]<king[kq])
32             {
33                 cnt--;
34                 //printf("%d vs %d = %d\n",ts,kq,cnt);
35                 kq++; ts--;
36             }
37             else
38             {
39                 if(tian[ts]>king[ks])
40                 {
41                     cnt++;
42                     //printf("%d vs %d = %d\n",ts,ks,cnt);
43                     ts--; ks--;
44                 }
45                 else if(tian[ts]<king[ks])
46                 {
47                     cnt--;
48                     //printf("%d vs %d = %d\n",ts,kq,cnt);
49                     ts--; kq++;
50                 }
51                 else
52                 {
53                     cnt-=(tian[ts]<king[kq]);
54                     //printf("%d vs %d = %d\n",ts,kq,cnt);
55                     ts--; kq++;
56                 }
57             }
58         }
59         printf("%d\n",cnt*200);
60     }
61 }

感觉这是一道还需要反复咀嚼一下的题目。

posted @ 2017-07-28 11:48  Dilthey  阅读(306)  评论(0)    收藏  举报