hdu1052(贪心算法解决田忌赛马)

题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1052
题目大意:
给你田忌和国王的马匹每匹所代表的值,值越高代表这个马越厉害。然后输出这种情况下的,田忌最多能赢多少银两。赢一场可以得200银两【注:可以为负值。比如输了三局,就是-600

题目思路:

贪心算法,在这就是分类讨论思想:
我们记田忌最快的马为QT,最慢的马为ST
记国王最快的马为QK,最慢的马为SK
那么可以分为以下情况:
1)ST>SK,就直接比,算赢一场
2)ST<SK,就让田忌的最慢的马与王最快的马相比,算输一场
3)ST==SK,我们需要再往下讨论如下:
*******3.1):QT>QK,直接比,记赢一场
*******3.2):QT<=QK,需要判断一下,
*****************3.2.1):如果ST<QK【注意:这里不是打错了,就是要判断田忌最慢的马是否小于王最快的马,因为要保证田忌每次输都应该是用最差的换掉王最好的】,就记输一次,用田忌最差的马换掉王最好的马。
*****************3.2.2):如果QT=QK,其实就相当于是场上所剩下的所有的马值都是一样的。
因为我们这个情况是在ST==SK和QT<=QK条件下的,如果QK==ST,那么只有一种情况就是ST==SK==QK==QT但是!!!!我们不能直接将其return 0 掉,因为ST、SK、QK、QT这四个是动态变化的有可能是最后中间出现了这种相等的情况,如果直接return0的话,之前找的就相当于是白找了,看下面的例子
所以满足这种"3.2.2"的情况的可能有:
3
77 77 77
77 77 77
如果单单只是上面这种一开始就进入这个情况,我们确实可以直接return 0掉

然而,也有可能是以下的情况:
4
76 77 77 77
77 77 77 78
这样子的话直接return0掉的话,就会导致答案错误,正确答案其实是-200,也就是说之前找的情况直接被覆盖了。
所以碰到这种情况我们处理方式就是,直接return win的值回来【注:win的值记录的是田忌累计的输赢情况】。这时候return win的值其实就相当于是将这只之前的输赢情况返回了,后面全是平局没有查找的必要了。

ac代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int Tian[1005];

int King[1005];

int n;//马匹数 

int race(){
    //sort第二个变量为数组的最后一个的再后一个位置 
    sort(Tian,Tian+n);//给马匹按照从小到大的顺序排序 
    sort(King,King+n);
    int win = 0;
    int Thead,Ttail;//记录田忌马的前后检测位置
    int Khead,Ktail;//国王的
    Thead = 0;
    Khead = 0;
    Ttail = n-1;
    Ktail = n-1;
    while(Thead<=Ttail){

        if(Tian[Thead]>King[Khead]){//两匹最慢的马直接比 
            win++;
            Thead++;
            Khead++;
            continue;
        }
        else if(Tian[Thead]<King[Khead]){//田忌的马与王最快的马比 
            win--;
            Thead++;
            Ktail--;
            continue;
        }else{//当两个最慢的马相等时 
            if(Tian[Ttail]>King[Ktail]){//两匹快马直接比 
                win++;
                Ttail--;
                Ktail--;
            }
            else{//田忌的快马不如王的快马快时 
            	if(King[Ktail]>Tian[Thead]){//当王的快马快于田忌的慢马时
            								//算田忌输一局
                win--;
                Thead++;
                Ktail--;
				}else{//因为在这之后全是相等的了,也就是平局,可以直接返回值了 
                return win;
				}

            }
            
        }
    }
	return win;
        
}


int main(){
    int ans;
    
    while(cin>>n){
        if(n==0){
            break;
        }
        for(int i = 0;i < n;i++){
            cin>>Tian[i];
        }
        for(int j = 0;j < n;j++){
            cin>>King[j];
        }
        ans = race();
        cout<<ans*200<<endl;
    }
    
    
    return 0;
    
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值