用贪心算法解决田忌赛马问题

题目描述

题目来源 BUPT ACM 洛谷P1650田忌赛马和这个类似

Problem Description

“田忌赛马”是中国历史上一个著名的故事。

大约2300年前,齐国大将田忌喜欢和国王赛马,并且约定:每赢一场,对方就要付200元。

假设已知田忌和国王的各自马匹的速度都不相同,请计算田忌最好的结果是什么。

Input

输入包含多组测试样例。

每组样例的第一行是一个整数n(n <= 1000),表示田忌和国王各自参赛的马匹数量。

接下来一行的n个整数表示田忌的马的速度,再接下来一行的n个整数表示国王的马的速度。

n为0时,表示输入数据的结束。

Output

每组数据输出一行,表示田忌最多能够赢得的金额。

输入样例

3
92 83 71
95 87 74
2
20 19
22 18
0

输出样例

200
0
思路分析

从小故事中我们可以领会到,田忌出马的策略其实就是贪心的策略,让马能赢就赢,做到“物尽其用”;(最慢的马)怎么也赢不了的时候,就“殊死一搏”,去挑战对方最快的马(注意这个时候挑战不一定输,也会有平局的现象出现),达到贪心中的利益最大化。

策略

1. 如果田忌最快的马比齐王最快的马快,则两者比(如果不这样可能会输);

2. 如果田忌最快的马比齐王最快的马慢,则拿田忌最慢的马与齐王最快的马比

(齐王拿出最快的马后,田忌怎么样都得输,不妨拿最慢的马比,让损失最小);

3. 如果田忌最快的马与齐王最快的马一样快,则比较双方最慢的马:

如果田忌最慢的马比齐王最慢的马快,则两者比

其他情况,拿田忌最慢的马与齐王最快的马比(这匹马无论如何都赢不了,不如与对方最快的马“同归于尽”)

AC Code
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std;
int a[1005],b[1005];
int main(){
    int n;
    cin>>n;
    while(n!=0){
        int sum=0;
        for(int i=1;i<=n;i++)
            cin>>a[i];  //田忌
        for(int i=1;i<=n;i++)
            cin>>b[i];  //齐王
        sort(a+1,a+1+n);  //由慢到快排序
        sort(b+1,b+1+n);
        int left_a=1,left_b=1;  //左指针指向较慢的一端
        int right_a=n,right_b=n;  //右指针指向较快的一端
        for(int i=1;i<=n;i++){
            if(a[right_a]>b[right_b]){  //田忌最快的马更快
                sum+=200;
                right_a--;
                right_b--;
            }else if(a[right_a]<b[right_b]){  //齐王最快的马更快
                sum-=200;
                left_a++;
                right_b--;
            }else{  //最快的马一样快,比较最慢的马
                if(a[left_a]>b[left_b]){  //田忌最慢的马更快
                    sum+=200;
                    left_a++;
                    left_b++;
                }else{  //最慢的马怎么也赢不了(输或平),直接挑战至尊强者——最快的马
                    if(a[left_a]<b[right_b])  //如果挑战平局的话,就不用掏钱了
                        sum-=200;             //(双方都只剩下一匹马,最慢的和最快的是同一个)
                    left_a++;
                    right_b--;
                }
            }
        }
        cout<<sum<<endl;
        cin>>n;
    }
    system("pause");
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值