hdu 1052 田忌赛马(贪心)

27 篇文章 1 订阅
自己写的时候,wa过好多次,总是漏了一些可能性,感觉自己现在拿到题没有办法看透他的本质,我一个学长拿到题总能用短到吓人的代码长度a掉,又快又短 ,分析问题时候脑子要清醒,有一种宏观的思想
题目大意:题目意思很好懂,田忌赛马都懂哈,先给你田忌的n匹马,给你齐王的n匹马。问你最多能得多少分,胜一场200分负一场-200分,平一场不得分。

             解题思路: 自己开始贪心的策略是先用田忌的快马与齐王的快马相比,>则胜一场,<则用田忌的慢马与齐王的快马相比。=的话这里没处理好,所以就WA了。看了下大牛的博客。讲下思路。

思路是每次先让慢马相比,如果>胜一场,<则拉下水,=要看自己的快马能不能赢,不能赢,则拉下水,能赢则赢一场。
下面文字来源于nyist_xiaod

1.若田忌最慢的马可以战胜齐王最慢的马,那么就让它战胜那匹慢马,胜利场次加1。(田忌最慢马 > 齐王最慢马)

2.若田忌最慢的马不能战胜齐王最慢的马,那么它更加不能战胜其他的马,那就让它输,而且输给齐王最快马,失败场次加1。(田忌最慢马 < 齐王最快马)

3.若田忌最慢的马与齐王最慢的马速度相等。此时,不能简单地认为与它打成平手就是最好情况,相反,打平是下下策,为什么呢?

因为自己后面的队友很有可能战胜此时对方的这匹慢马,所以就算自己输一场,队友也能帮忙赢回一场,而胜一场,输一场的收益和打平一场的收益是一样的,而且自己输的时候可以拉对方最快的马下水,给己方最快的马创造更大的胜利机会(因为它失去了一个强劲的对手),也就是说己方最快的马很可能因为自己的牺牲再胜利一场,从这个角度看,还是自己故意输掉比较好。


但是,还有一点需要注意,当自己放水前,如果己方最快的马原本就比对方最快的马快,然后还输给对方最快的马,那么己方最快的马的才华就浪费了,为什么?

很简单,它原本就能赢,需要你放水么?- -!换句话说,这种情况下,自己的牺牲没有一点价值。

所以,在放水时,一定要保证己方最快马不快于对方最快马。满足此条件后,让己方最慢马与对方最快马去比赛(有可能平局),这样,田忌的马就得到了充分的利用。

  1. #include<iostream>  
  2. #include<cstring>  
  3. #include<algorithm>  
  4. #include<cstdio>  
  5. using namespace std;  
  6.   
  7. int a[1005];  
  8. int b[1005];  
  9. int cmp(int a,int b)  
  10. {  
  11.     if(a>b) return 1;  
  12.     return 0;  
  13. }  
  14.   
  15. int main()  
  16. {  
  17.     int n,i,j,sum,len1,len2;  
  18.     while(scanf("%d",&n)&&n)  
  19.     {  
  20.         for(i=0;i<n;i++)  
  21.             scanf("%d",&a[i]);  
  22.         sort(a,a+n,cmp); //田忌的马从快到慢排序  
  23.         for(i=0;i<n;i++)  
  24.             scanf("%d",&b[i]);  
  25.         sort(b,b+n,cmp); //齐王的马从快到慢排序  
  26.         i=0,j=0;  
  27.         len1=len2=n-1;  //最慢的马的位置  
  28.         sum=0;  
  29.         while(i<=len1&&j<=len2)  
  30.         {  
  31.             if(a[len1]>b[len2]) //田忌慢马>齐王慢马  
  32.             {  
  33.                 sum++;  //先胜一场  
  34.                 len1--,len2--;  
  35.             }  
  36.             else if(a[len1]<b[len2])  
  37.             {  
  38.                  sum--;    //拿最慢的马与齐王快马赛  
  39.                  j++;  
  40.                  len1--;  
  41.             }  
  42.             else  
  43.             {  
  44.                 if(i<len1) //除去最快的马还有别的马  
  45.                 {  
  46.                     if(a[i]<=b[j])  //田忌的快马赢不了  
  47.                     {  
  48.                         if(a[len1]<b[j])  
  49.                             sum--;  
  50.                         len1--,j++;  
  51.                     }  
  52.                     else  
  53.                     {  
  54.                         sum++;  //快马赢  
  55.                         i++; j++;  
  56.                     }  
  57.                 }  
  58.                 else  
  59.                 {  
  60.                     len1--,len2--; //平局  
  61.                 }  
  62.             }  
  63.         }  
  64.   
  65.         printf("%d\n",sum*200);  
  66.     }  
  67.     return 0;  
  68. }  
  69.   
  70. /* 
  71. 4 
  72. 70 65 50 20 
  73. 70 65 55 20 
  74. 4 
  75. 70 60 50 20 
  76. 70 65 55 20 
  77. 4 
  78. 70 55 50 20 
  79. 70 65 55 20 
  80. */ 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值