1489. 田忌赛马(贪心)

2023-11-12

这是中国历史上的一个著名故事。

大约 2300 年前,田忌是齐国的一位将军,他喜欢与国王等人赛马。

田忌和国王都有三匹不同等级的马----下马、中马、上马。

规则是一场比赛要进行三个回合,每匹马进行一回合的较量,单回合的获胜者可以从失败者那里得到 200 银元。

比赛的时候,国王总是用自己的上马对田忌的上马,中马对中马,下马对下马。

由于国王每个等级的马都比田忌的马强一些,所以比赛了几次,田忌都失败了,每次国王都能从田忌那里拿走 600 银元。

田忌对此深感不满,直到他遇到了著名的军事家孙膑,利用孙膑给他出的主意,田忌终于在与国王的赛马中取得了胜利,拿走了国王的 200 银元。

其实胜利的方法非常简单,他用下马对战国王的上马,上马对战国王的中马,中马对战国王的下马,这样虽然第一回合输了,但是后两回合都胜了,最终两胜一负,取得了比赛胜利。

在这里插入图片描述

如果田忌活在如今,那么他可能会嘲笑自己当初的愚蠢。

重要的是,如果他现在正参加 ACM 竞赛,他可能会发现赛马问题可以简单地看作是在二分图中找到最大匹配项。

在一侧画田忌的马,在另一侧画国王的马,只要田忌的一匹马能够击败国王的一匹马,我们就在这两匹马之间画一条边。

然后,赢尽可能多的回合,就变成了在这个二分图中找到最大匹配。

如果存在平局,问题会变得更加复杂,他需要为所有可能的边分配权重 0、1 或 −1,并找到最大加权的完美匹配…

然而,赛马问题其实是二分图匹配的一种非常特殊的情况。

该图由马的速度决定,速度快的总是能击败速度慢的。

这种情况下,加权二分图匹配算法就显得大材小用了。

在这个问题中,你需要编写一个程序,来解决这一特殊的匹配问题。

输入格式
输入包含最多 50 组测试数据。

每组数据第一行包含一个整数 n,表示一方马的数量。

第二行包含 n 个整数,是田忌的马的速度。

第三行包含 n 个整数,是国王的马的速度。

输入的最后一行为 0,表示输入结束。

输出格式
每组数据输出一个占一行的整数,表示田忌最多可以获得多少银元。

数据范围
1≤n≤1000
马的速度不超过 1000。

输入样例:

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

输出样例:

200
0
0

思路分析

在这里插入图片描述
      假设田忌最快的马为f1,最慢的马为s1,国王最快的马为f2,最慢的马为s2。因为我们想让田忌赢尽可能多的比赛(温馨提示:VS代表让两人对应编号的马进行比赛)。
则有以下情况:

  1. s1>s2时,让s1 VS s2,此时田忌会赢一场。
  2. s1<s2时,让s1 VS f2,因为田忌的马s1 是最慢的马,它比国王最慢的马s2还慢,所以田忌的这匹马,无论与国王的哪匹马相比都是输的。此时可以让田忌最垃圾的马去打国王最厉害的马,即让这匹马当炮灰去把国王的马的整体速度给拉下来,这样能让田忌在接下来的比赛中能有更大的机会去赢。
  3. s1=s2时,田忌最慢的马和国王最慢的马速度相等,即此时田忌的马要么是输,要么是平局,因为输的话可以拿它去当炮灰把国王的马的整体速度给拉下来,这样能让田忌在接下来的比赛中能有更大的机会去赢。所以此时无法确定哪种选择是更优的。因此在此条件下再来比较最快的马看看(思考一下:为什么要比较最快的马呢?因为想在国王必赢的极端条件下用最慢的马来当炮灰)。
           3.1 f1>f2时,让f1 VS f2,因为田忌最快的马f1 比国王最快的马f2都快,所以田忌这匹马是必赢的,让它去打国王最快的马,这既能赢一场比赛,又把国王的马的速度给拉下来 。
           3.2 f1<f2时,让s1 VS f2,因为田忌最快的马f1 比国王最快的马f2都慢,所以国王这匹马是必赢的,此时只能让田忌最慢的马s1去当炮灰,去把国王的马的速度给拉下来 。
           3.3 f1=f2时,让s1 VS f2,因为此时 s1=s2且 f1=f2。s1有两种选择
           ① s1 VS s2。(平局)
           ② s1 VS f2(因为有可能s1 = f2,所以田忌有可能输一场)。
           假设情况① s1 VS s2。(平局)能取得最优解。
    在这里插入图片描述
    因为 s1 VS s2了,所以f2可以选择田忌的马中的任何一匹马进行比赛设其为x(其中x不包括 s1),此时田忌的马有如下的速度关系, f1>=x>=s1
           假设f1>x。此时田忌净输一场( s1 VS s2,平局, x VS f2,因为f2=f1>x,所以田忌输)。
           我们来看看这种条件下的第二种情况,② s1 VS f2情况会如何。
    在这里插入图片描述
           此时田忌最坏情况下净输一场( s1 VS f2,田忌输, x VS s2,因为x>=s1=s2,当x=s2时平局(田忌净输一场),当x>s2时,田忌赢(两局来看田忌不赢不输))。即情况② s1 VS f2,在最坏的情况下,也不会比情况①差,且情况②有可能比它更好。
           假设f1=x。此时又有两种情况。
    在这里插入图片描述
           当x=s1时,此时有 f1=f2=x=s1=s2。所以情况① s1 VS s2( s1 VS s2平局,x VS f2平局)和② s1 VS f2( s1 VS f2平局,x VS s2平局)两者等价,即两局都是平局。
           当x>s1时,此时有 f1=f2=x>s1=s2。所以情况① s1 VS s2( s1 VS s2平局,x VS f2平局)和② s1 VS f2( s1 VS f2田忌输,x VS s2田忌赢)即从两局总和来看也是平局。
           所以综上所述,情况② s1 VS f2在最坏的情况下也不会比情况① s1 VS s2差,即情况②一定有最优解。注意:这里不是说情况①没有最优解,只是情况①不一定有最优解。但情况②一定有最优解。即3.3 f1=f2时,让s1 VS f2能取得最优解。
    在这里插入图片描述
    在这里插入图片描述
          注意点:是不是还会有小伙伴说我还没思考x<s1的情况。因为x>=s1所以不用考虑。

代码

#include <iostream>
#include<algorithm>
using namespace std;
int a[1005],b[1005];//a数组存储田忌的马的速度,b数组存储国王的马的速度
//判断某场比赛谁赢
int judge(int x,int y){
    if(a[x]>b[y])
        return 1;//田忌赢
    if(a[x]<b[y])
        return -1;//田忌输
    return 0;//平局
}

int main()
{
    int n;
    while(cin>>n,n){//输入多组数据
        for(int i=0;i<n;i++)//输入田忌的马的速度
            cin>>a[i];
        for(int i=0;i<n;i++)//输入国王的马的速度
            cin>>b[i];
        sort(a,a+n,greater<int>());//注意点:一定要将马的速度从大到小排序
        sort(b,b+n,greater<int>());
        int f1=0,f2=0,s1=n-1,s2=n-1;
        int res=0;
        while(f1<=s1){//每次安排两匹马进行比赛,如果还有马没安排比赛则继续循环
            if(a[s1]>b[s2]){//s1>s2时,让s1 VS s2
                res++;//田忌赢
                s1--;
                s2--;
            }else if(a[s1]<b[s2]){//s1<s2时,让s1 VS f2
                res--;//田忌输
                s1--;
                f2++;
            }else{//s1=s2时,比较最快的马的情况
                if(a[f1]>b[f2]){// f1>f2时,让f1 VS f2
                    res++;//田忌赢
                    f1++;
                    f2++;
                }else{//f1<f2时和f1=f2时都是让s1 VS f2
                    res+=judge(s1,f2);//这两种情况田忌有输有平,要根据情况决定
                    s1--;
                    f2++;
                }
            }
        }
        cout<<res*200<<endl;//田忌最多可以获得多少银元,注意点一定要乘200
    }
    return 0;
}

写稿不易,如果对您有帮助请帮忙点个赞呗。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

1489. 田忌赛马(贪心) 的相关文章

  • 向进度条添加百分比文本 C#

    我有一个方法可以显示进程栏何时正在执行以及何时成功完成 我工作得很好 但我想添加一个百分比 如果完成 则显示 100 如果卡在某个地方 则显示更少 我在网上做了一些研究 但我无法适应我正在寻找的解决方案 这是我的代码 private voi
  • ClickOnce 应用程序错误:部署和应用程序没有匹配的安全区域

    我在 IE 中使用 FireFox 和 Chrome 的 ClickOnce 应用程序时遇到问题 它工作正常 异常的详细信息是 PLATFORM VERSION INFO Windows 6 1 7600 0 Win32NT Common
  • 使用 LINQ2SQL 在 ASP.NET MVC 中的各种模型存储库之间共享数据上下文

    我的应用程序中有 2 个存储库 每个存储库都有自己的数据上下文对象 最终结果是我尝试将从一个存储库检索到的对象附加到从另一个存储库检索到的对象 这会导致异常 Use 构造函数注入将 DataContext 注入每个存储库 public cl
  • 使用 Newtonsoft 和 C# 反序列化嵌套 JSON

    我正在尝试解析来自 Rest API 的 Json 响应 我可以获得很好的响应并创建了一些类模型 我正在使用 Newtonsoft 的 Json Net 我的响应中不断收到空值 并且不确定我的模型设置是否正确或缺少某些内容 例如 我想要获取
  • 回发后刷新时提示确认表单重新提交。我做错了什么?

    我有一个以空白 默认状态启动的仪表板 我让用户能够将保存的状态加载到仪表板中 当他们单击 应用 按钮时 我运行以下代码 function CloseAndSave var radUpload find radUpload1ID var in
  • 如何使用 LINQ2SQL 连接两个不同上下文的表?

    我的应用程序中有 2 个数据上下文 不同的数据库 并且需要能够通过上下文 B 中的表的右连接来查询上下文 A 中的表 我该如何在 LINQ2SQL 中执行此操作 Why 我们正在使用 SaaS 产品来跟踪我们的时间 项目等 并希望向该产品发
  • 在 C 中初始化变量

    我知道有时如果你不初始化int 如果打印整数 您将得到一个随机数 但将所有内容初始化为零似乎有点愚蠢 我问这个问题是因为我正在评论我的 C 项目 而且我对缩进非常直接 并且它可以完全编译 90 90 谢谢 Stackoverflow 但我想
  • 在 Visual Studio 2010 中从 Fortran 调用 C++ 函数

    我想从 Fortran 调用 C 函数 为此 我在 Visual Studio 2010 中创建了一个 FORTRAN 项目 之后 我将一个 Cpp 项目添加到该 FORTRAN 项目中 当我要构建程序时出现以下错误 Error 1 unr
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • 外键与独立关系 - Entity Framework 5 有改进吗?

    我读过了several http www ladislavmrnka com 2011 05 foreign key vs independent associations in ef 4 文章和问题 https stackoverflow
  • CMake 无法确定目标的链接器语言

    首先 我查看了this https stackoverflow com questions 11801186 cmake unable to determine linker language with c发帖并找不到解决我的问题的方法 我
  • AES 128 CBC 蒙特卡罗测试

    我正在 AES 128 CBC 上执行 MCT 如中所述http csrc nist gov groups STM cavp documents aes AESAVS pdf http csrc nist gov groups STM ca
  • 如何设置 log4net 每天将我的文件记录到不同的文件夹中?

    我想将每天的所有日志保存在名为 YYYYMMdd 的文件夹中 log4net 应该根据系统日期时间处理创建新文件夹 我如何设置它 我想将一天中的所有日志保存到 n 个 1MB 的文件中 我不想重写旧文件 但想真正拥有一天中的所有日志 我该如
  • 为什么 gcc 抱怨“错误:模板参数 '0' 的类型 'intT' 取决于模板参数”?

    我的编译器是gcc 4 9 0 以下代码无法编译 template
  • 使用 C# 读取 Soap 消息

  • C++ 函数重载类似转换

    我收到一个错误 指出两个重载具有相似的转换 我尝试了太多的事情 但没有任何帮助 这是那段代码 CString GetInput int numberOfInput BOOL clearBuffer FALSE UINT timeout IN
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装
  • 无法接收 UDP Windows RT

    我正在为 Windows 8 RT 编写一个 Windows Store Metro Modern RT 应用程序 需要在端口 49030 上接收 UDP 数据包 但我似乎无法接收任何数据包 我已按照使用教程进行操作DatagramSock

随机推荐

  • JavaScript基础--内置对象之Math对象

    Math 对象不是构造函数 不需要new 它具有数学常数和函数的属性和方法 跟数学相关的运算 求绝对值 取整 最大值等 可以使用 Math 中的成员 1 Math对象常用方法 1 1 Max floor Max floor floor表示地
  • sql的基本操作详解

    一 什么是视图 视图 view 是一种虚拟存在的表 是一个逻辑表 本身并不包含数据 作为一个select语句保存在数据字典中的 二 为什么要用视图 视图隐藏了底层的表结构 简化了数据访问操作 客户端不再需要底层表的机构及其之间的关系 视图是
  • UE4 C++获取StaticMesh详细信息

    h UFUNCTION BlueprintCallable Category FunTool void GetStaticMeshDetails UStaticMesh Staticmesh TMap
  • 做期货的时候想到自己挣的钱都是别人亏的钱吗?

    1 换股法 当觉得自己的理财产品实在是没有什么时机了 就选一只与该理财产品价格差不多的 有时机上涨的理财产品来换 也便是等价 或根本等价 换入有上涨期望的理财产品 让后边买入的理财产品上涨后的赢利来抵消前面买入的理财产品因跌落而发生的亏本
  • Spring事务配置文件方式

  • BOOST 库中filesyatem 库的学习

    FileSyatem 库的学习 库的使用方式 嵌入源码的形式 define BOOST SYSTEN NO LIB define BOOST FILESYSTEM NO LIB include
  • 配置文件(properties类)

    基本介绍 1 专门用于读写配置文件的集合类 配置文件格式 键 值 2 注意 键值对 不需要空格 值 不需要用引号 默认类型 String 3 Properties的常见方法 1 load 加载配置文件的键值对到Properties对象 2
  • Win11怎么设置电脑开机密码和锁屏密码

    相信很多用户都已经用上了微软公司为大家提供的全新Win11系统了 Win11与Win10系统有很大区别 不仅仅体现在界面设计和UI上面 狠多以前Win10用户固定的功能有些取消了 有些挪位置了 这让用惯了Win10系统的用户非常不习惯 下面
  • Lua和C++交互详细总结

    转自 http cn cocos2d x org tutorial show id 1474 一 Lua堆栈 要理解Lua和C 交互 首先要理解Lua堆栈 简单来说 Lua和C C 语言通信的主要方法是一个无处不在的虚拟栈 栈的特点是先进后
  • Scrum猪和鸡的故事

    本文转载至 http blog csdn net fen0707 article details 8979942 一天 一头猪和一只鸡在路上散步 鸡看了一下猪说 嗨 我们合伙开一家餐馆怎么样 猪回头看了一下鸡说 好主意 那你准备给餐馆卖什么
  • Java Error org.apache.thrift.transport.TTransportException

    org apache thrift transport TTransportException java net ConnectException Connection refused connect org apache thrift t
  • 利用Python绘制中国新型冠状病毒疫情图(国家和省)

    大数据课程设计上来就要求绘制一个地图可以反应出来中国各个省份每日疫情的人数 包括确诊 疑似 死亡 治愈 如下图所示 这里用到了Python中的pyecharts库 点此了解详细信息 1 先来将需要的模块导入进来 import request
  • Windows 系统上如何安装 Python 环境(详细教程)

    一 下载 64位下载链接 https www python org ftp python 3 7 9 python 3 7 9 amd64 exe 32位下载链接 https www python org ftp python 3 7 9
  • QCheckBox复选框状态设置、信号绑定

    一 QCheckBox有两种设置状态 1 setCheckState Qt Checked 设置状态并且发送信号出去 eg for auto itr m mCheckBoxNum begin itr m mCheckBox end itr
  • (Java)leetcode-814 Binary Tree Pruning(二叉树剪枝)

    题目描述 给定二叉树根结点 root 此外树的每个结点的值要么是 0 要么是 1 返回移除了所有不包含 1 的子树的原二叉树 节点 X 的子树为 X 本身 以及所有 X 的后代 示例1 输入 1 null 0 0 1 输出 1 null 0
  • JDBC工作原理

    JDBC程序描述为包含如下过程的应用 1 引入一个必要的类2 加载JDBC驱动程序3 标识数据源 URL Username Password 4 分配一个Connection对象5 分配一个Statement对象6 使用该Statement
  • 阿里云部署Stable Diffusion

    系列文章目录 本地部署Stable Diffusion教程 亲测可以安装成功 Stable Diffusion界面参数及模型使用 谷歌Colab云端部署Stable Diffusion 进行绘图 文章目录 系列文章目录 前言 一 AIGC是
  • 外挂原理

    一 前言 所谓游戏外挂 其实是一种游戏外辅程序 它可以协助玩家自动产生游戏动作 修 改游戏网络数据包以及修改游 戏内存数据等 以实现玩家用最少的时间和金钱去完成功力升级和过关斩将 虽然 现 在对游戏外挂程序的 合法 身份众说纷纭 在这里我不
  • 数据结构——二叉树 增加、删除、查询

    二叉树系统 public class BinarySystem public static void main String args BinaryDomain root null 定义头结点 new BinaryAction manage
  • 1489. 田忌赛马(贪心)

    这是中国历史上的一个著名故事 大约 2300 年前 田忌是齐国的一位将军 他喜欢与国王等人赛马 田忌和国王都有三匹不同等级的马 下马 中马 上马 规则是一场比赛要进行三个回合 每匹马进行一回合的较量 单回合的获胜者可以从失败者那里得到 20