zoukankan      html  css  js  c++  java
  • 洛谷P1650 赛马[2017年5月计划 清北学堂51精英班Day1]

    P1650 赛马

    题目描述

    我国历史上有个著名的故事: 那是在2300年以前。齐国的大将军田忌喜欢赛马。他经常和齐王赛马。他和齐王都有三匹马:常规马,上级马,超级马。一共赛三局,每局的胜者可以从负者这 里取得200银币。每匹马只能用一次。齐王的马好,同等级的马,齐王的总是比田忌的要好一点。于是每次和齐王赛马,田忌总会输600银币。

    田忌很沮丧,直到他遇到了著名的军师――孙膑。田忌采用了孙膑的计策之后,三场比赛下来,轻松而优雅地赢了齐王200银币。这实在是个很简单的计 策。由于齐王总是先出最好的马,再出次好的,所以田忌用常规马对齐王的超级马,用自己的超级马对齐王的上级马,用自己的上级马对齐王的常规马,以两胜一负 的战绩赢得200银币。实在很简单。

    如果不止三匹马怎么办?这个问题很显然可以转化成一个二分图最佳匹配的问题。把田忌的马放左边,把齐王的马放右边。田忌的马A和齐王的B之间,如果 田忌的马胜,则连一条权为200的边;如果平局,则连一条权为0的边;如果输,则连一条权为-200的边……如果你不会求最佳匹配,用最小费用最大流也可 以啊。 然而,赛马问题是一种特殊的二分图最佳匹配的问题,上面的算法过于先进了,简直是杀鸡用牛刀。现在,就请你设计一个简单的算法解决这个问题。

    输入输出格式

    输入格式:

    第一行一个整数n,表示他们各有几匹马(两人拥有的马的数目相同)。第二行n个整数,每个整数都代 表田忌的某匹马的速度值(0 <= 速度值<= 100)。第三行n个整数,描述齐王的马的速度值。两马相遇,根据速度值的大小就可以知道哪匹马会胜出。如果速度值相同,则和局,谁也不拿钱。

    【数据规模】

    对于20%的数据,1<=N<=65;

    对于40%的数据,1<=N<=250;

    对于100%的数据,1<=N<=2000。

    输出格式:

    仅一行,一个整数,表示田忌最大能得到多少银币。

    输入输出样例

    输入样例#1:
    3
    92 83 71
    95 87 74
    输出样例#1:
    200

    这是一道让人吐血的好题。。

    先来想想贪心策略(这里一定要理清思路,慢慢来,别急):
    如果总是用最弱的马 去打对面最强的马,可能不是最优,因为这里有平局的情况存在,选择平局可能比赢给最强的马更合算
    (譬如:田忌 2 3 10 齐威王:2 8 9)
    因此,我们要这样去分析:
    先看最弱的马之间的实力,如果我方最弱的马比对方最弱的马强,就直接怼掉。这个比较显然,既然我方最弱的马更强,那么我方其它马一定可以怼掉对方最弱的马,但杀鸡焉用牛刀?
    如果我方的马比对方的马弱或者相等:
    有一种策略是用最弱的马去怼最强的马,让“炮灰”的作用发挥到极值,
    另一种策略是先看最强的马之间的关系。

    我们来分别讨论这两种策略,并证明两种策略都是正确的:
    1、用最弱的马去怼最强的马,这样输了一盘,但这一盘是早晚要输的。如果最弱的马等于对方最弱的马,那么怼掉对方最强马,一定有其它马可以赢回来;如果最弱的马小于对方最弱的马,那么必然小于对方所有马,这是必然的。因此应让它去怼掉对方最强的,让我放最强的能够成功得分道路进一步开阔。
    2、先看最强的马之间的关系。如果我方最强马比对方更强,就怼掉,否则就应该让最弱的马去怼对方最强的马。因为我方最强的马虽然打不过敌方最强马,但说不定可以打过第二强、第三强……但是最弱的马却一定赢不了所有的马。
    两条结合着来,差不多了就。。。
    但是还有一种特殊情况:最弱的马平局,最强的马平局,且最弱的马等于最强的马
    这时所有对决均为平局,直接输出答案即可。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #define max(a,b) ((a) > (b) ? (a) : (b))
    #define min(a,b) ((a) > (b) ? (b) : (a))
    #define lowbit(a) ((a) & (-(a)))
    
    int read()
    {
        int x = 0;char ch = getchar();char c = ch;
        while(ch > '9' || ch < '0')c = ch, ch = getchar();
        while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
        if(c == '-')return -x;
        return x;
    }
    const int INF = 0x3f3f3f3f;
    const int MAXN = 2000 + 10;
    
    int n,tian[MAXN],qi[MAXN];
    int ans;
    
    
    inline void init()
    {
        n = read();
        for(int i = 1;i <= n;i ++)
        {
            tian[i] = read();
        }
        std::sort(tian + 1, tian + 1 + n);
        for(int j = 1;j <= n;j ++)
        {
            qi[j] = read();
        }
        std::sort(qi + 1, qi + 1 + n);
    }
    inline void put()
    {
        printf("%d", ans * 200);
    }
    inline void tan()
    {
        int head1 = 1,tail1 = n,head2 = 1,tail2 = n;
        while(head1 <= tail1)
        {
            if(tian[head1] > qi[head2]) head1 ++,head2 ++,ans ++; 
            else if(tian[head1] < qi[head2]) head1 ++,tail2 --,ans --;
            else//平局
            {
                if(tian[tail1] > qi[tail2])tail1 --, tail2 --, ans ++;
                else if(tian[head1] < qi[tail2])head1 ++, tail2 --, ans--;//注意!!
                else break;
            }
        }
    }
    
    int main()
    {
        init();
        tan();
        put();
        return 0;
    }
    










  • 相关阅读:
    Microsoft Excel 不能使用对象链接和嵌入的错误/cannot use object linking and enbedding
    (转)QML代码与现有Qt UI代码整合
    vs2012编译Qwt
    参数和返回类型也可以多态
    多态的运行
    调用哪个方法
    继承的意义
    设计继承树2
    设计继承树1
    了解继承
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/6899378.html
Copyright © 2011-2022 走看看