POJ - 2287 Tian Ji -- The Horse Racing

news2024/12/26 14:00:22

题目来源

2287 -- Tian Ji -- The Horse Racing (poj.org)

题目描述

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

这个故事发生在2300年前,田忌是齐国的一个大官,他喜欢和齐王以及其他公子赛马。

田忌和齐王都有三类马,分别是下等马,中等马,上等马。

比赛一共进行三轮,每匹马只能在某一轮比赛中使用。每一轮的胜者可以从败者获得200银币。

齐王是齐国最有权势的人,因此他的马都非常好,每个级别的马都要比田忌的同级别的马更好。因此,田忌每次都会输600银币给齐王。

田忌为此非常苦恼,直到他遇见了孙膑,这个中国历史上最有名的军师之一。孙膑为田忌提供了如下策略,让田忌在接下来的比赛中赢回了200银币。这是一个非常简单的策略,即:

  • 田忌的下等马 vs 国君的上等马(田忌输,失去200银币)
  • 田忌的中等马 vs 国君的下等马(田忌赢,获得200银币)
  • 田忌的上等马 vs 国君的中等马(田忌赢,获得200银币)

其实上面的赛马问题可以简单地看成是:二分图中寻找最大匹配。

把田忌的马画在一遍,把齐王的马画在另一边。

田忌的马只要能战胜齐王的马,我们就在这两匹马之间画一道连接线,表示我们希望让这两匹马进行匹配比赛。

那么,田忌赢得尽可能多的回合,其实就是在这个图中找到最大匹配。

如果存在平手,那么问题就会变得更佳复杂,他需要为所有可能的变分配权重0、1或-1,并找到一个最大的加权完美匹配。

然后,赛马问题是一个非常特殊的二分图匹配问题。这张图是由马的速度决定的。速度较快的顶点总是胜过速度较慢的顶点。在这种情况下,加权二分图匹配算法显得有点大材小用了。

请你设计一个算法来解决这种特殊匹配问题。

输入描述

最多输入50组用例。

每组用例:

  • 第一行为一个整数n(n ≤ 100)表示每一方马的数量。
  • 第二行为n个整数,表示田忌的马的速度。
  • 第三行为n个整数,表示齐王的马的速度。

输入的结束条件是,在最后一组用例之后输入只有'0'的一行。

输出描述

对每组用例输出一行,每行包含一个整数,表示该组用例下,田忌所能获得最大银币数。

用例

输入3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0
输出200
0
0
说明

题目解析

本题可以使用贪心思维去解决问题。

即:要想田忌获得银币最多,则应该让田忌输的最少,那么如何让田忌输的最少呢?

那就是用田忌 "必输的" 且 "最慢的" 马 去消耗掉 齐王最快的马。

因此,我们需要先将田忌和齐王的马进行升序,这样就能找到最慢和最快的马。

  • 如果田忌最快的马 > 齐王最快的马,则此轮田忌胜出
  • 如果田忌最快的马 < 齐王最快的马,则此轮田忌必输,但是为了保留住田忌最快的马,我们应该让田忌把最慢的马拿出来比赛,这样就会以最小代价输。
  • 如果条件最快的马 == 齐王最快的马,则此轮田忌平局,但是代价确实失去了最快的马,此时我们应该考虑从田忌的马中,找到一匹必输的、且最慢的马的去消耗掉齐王的最快的马,这样虽然此轮输了,但是田忌只是将必输的那匹马提前输了而已,好处是,保留住了最快的马。因此接下来我们应该找到田忌必输的,且最慢的马。
  1. 如果田忌最慢的马 > 齐王最慢的马,则当前田忌最慢的马不是田忌必输的、最慢的马,我们应该继续寻找
  2. 如果田忌最慢的马 < 齐王最慢的马,则当前田忌最慢的马就是田忌必输的、且最慢的马,我们应该拿这匹马和齐王最快的马比赛
  3. 如果田忌最慢的马 == 齐王最慢的马,则当前田忌最慢的马不是田忌必输的且最慢的马,我们应该继续寻找

JS算法源码

/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const lines = [];

rl.on("line", (line) => {
  if (line == "0") {
    const cases = [];

    for (let i = 0; i < lines.length; i += 3) {
      const n = parseInt(lines[i]);
      const a = lines[i + 1].split(" ").map(Number); // 田忌的马速度数组
      const b = lines[i + 2].split(" ").map(Number); // 齐王的马速度数组
      cases.push([n, a, b]);
    }

    getResult(cases);

    lines.length = 0;
  } else {
    lines.push(line);
  }
});

function getResult(cases) {
  for (let c of cases) {
    const n = c[0];
    const a = c[1];
    const b = c[2];

    a.sort((a, b) => a - b);
    b.sort((a, b) => a - b);

    let la = 0; // 指向田忌最慢的马
    let ra = n - 1; // 指向田忌最快的马

    let lb = 0; // 指向齐王最慢的马
    let rb = n - 1; // 指向齐王最快的马

    let ans = 0; // 记录田忌获得银币数

    while (la <= ra) {
      if (a[ra] > b[rb]) {
        // 田忌最快的马 比 齐王最快的马要快, 则直接比
        ans += 200;
        ra--;
        rb--;
      } else if (a[ra] < b[rb]) {
        // 田忌最快的马 比 齐王最快的马要慢, 则结果肯定输, 为了保留田忌最快的马, 我们应该用田忌最慢的马去消耗掉齐王最快的马
        ans -= 200;
        la++;
        rb--;
      } else {
        // 田忌最快的马 和 齐王最快的 速度相同, 此时如果平局的话,则会让田忌损失最快的马,因此我们应该找到田忌最慢的马, 即田忌必输的马来消耗掉齐王最快的马
        if (a[la] > b[lb]) {
          // 如果田忌最慢的马 比 齐王最慢的马 快, 则此时田忌最慢的马不是必输的马
          ans += 200;
          la++;
          lb++;
        } else {
          // 如果田忌最慢的马速度 <= 齐王最慢的马速度, 此时应该让田忌最慢的马 去消耗  齐王最快的马

          // 如果齐王最快的马速度 > 田忌最慢的马速度,则田忌失去银币
          // 如果齐王最快的马速度 == 田忌最慢的马速度,则田忌不失去银币
          if (b[rb] > a[la]) ans -= 200;
          la++;
          rb--;
        }
      }
    }

    console.log(ans);
  }
}

 

Java算法源码

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
  static class Case {
    int n;
    int[] a; // 田忌的马速度数组
    int[] b; // 齐王的马速度数组

    public Case(int n, int[] a, int[] b) {
      this.n = n;
      this.a = a;
      this.b = b;
    }
  }

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    ArrayList<Case> cases = new ArrayList<>();
    // POJ Java只支持jdk1.5, 因此如果需要在POJ验证的话,需要替换为下面更低级的语法
    //    ArrayList cases = new ArrayList();

    while (true) {
      String line = sc.next();

      if ("0".equals(line)) {
        getResult(cases);
        break;
      } else {
        int n = Integer.parseInt(line);
        int[] a = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        int[] b = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        // POJ Java只支持jdk1.5, 因此如果需要在POJ验证的话,需要替换为下面更低级的语法
        //        int[] a = new int[n];
        //        for (int i = 0; i < n; i++) a[i] = Integer.parseInt(sc.next());
        //
        //        int[] b = new int[n];
        //        for (int i = 0; i < n; i++) b[i] = Integer.parseInt(sc.next());

        cases.add(new Case(n, a, b));
      }
    }
  }

  public static void getResult(ArrayList<Case> cases) {
    for (Case c : cases) {
      int n = c.n;
      int[] a = c.a;
      int[] b = c.b;

      Arrays.sort(a);
      Arrays.sort(b);

      int la = 0; // 指向田忌最慢的马
      int ra = n - 1; // 指向田忌最快的马

      int lb = 0; // 指向齐王最慢的马
      int rb = n - 1; // 指向齐王最快的马

      int ans = 0; // 记录田忌获得银币数

      while (la <= ra) {
        if (a[ra] > b[rb]) {
          // 田忌最快的马 比 齐王最快的马要快, 则直接比
          ans += 200;
          ra--;
          rb--;
        } else if (a[ra] < b[rb]) {
          // 田忌最快的马 比 齐王最快的马要慢, 则结果肯定输, 为了保留田忌最快的马, 我们应该用田忌最慢的马去消耗掉齐王最快的马
          ans -= 200;
          la++;
          rb--;
        } else {
          // 田忌最快的马 和 齐王最快的 速度相同, 此时如果平局的话,则会让田忌损失最快的马,因此我们应该找到田忌最慢的马, 即田忌必输的马来消耗掉齐王最快的马
          if (a[la] > b[lb]) {
            // 如果田忌最慢的马 比 齐王最慢的马 快, 则此时田忌最慢的马不是必输的马
            ans += 200;
            la++;
            lb++;
          } else {
            // 如果田忌最慢的马速度 <= 齐王最慢的马速度, 此时应该让田忌最慢的马 去消耗  齐王最快的马

            // 如果齐王最快的马速度 > 田忌最慢的马速度,则田忌失去银币
            // 如果齐王最快的马速度 == 田忌最慢的马速度,则田忌不失去银币
            if (b[rb] > a[la]) ans -= 200;
            la++;
            rb--;
          }
        }
      }

      System.out.println(ans);
    }
  }
}

 

Python算法源码

# 算法入口
def getResult(cases):
    for case in cases:
        n = case[0]
        a = case[1]
        b = case[2]

        a.sort()
        b.sort()

        la = 0  # 指向田忌最慢的马
        ra = n - 1  # 指向田忌最快的马

        lb = 0  # 指向齐王最慢的马
        rb = n - 1  # 指向齐王最快的马

        ans = 0  # 记录田忌获得银币数

        while la <= ra:
            if a[ra] > b[rb]:
                #  田忌最快的马 比 齐王最快的马要快, 则直接比
                ans += 200
                ra -= 1
                rb -= 1
            elif a[ra] < b[rb]:
                # 田忌最快的马 比 齐王最快的马要慢, 则结果肯定输, 为了保留田忌最快的马, 我们应该用田忌最慢的马去消耗掉齐王最快的马
                ans -= 200
                la += 1
                rb -= 1
            else:
                # 田忌最快的马 和 齐王最快的 速度相同, 此时如果平局的话,则会让田忌损失最快的马,因此我们应该找到田忌最慢的马, 即田忌必输的马来消耗掉齐王最快的马
                if a[la] > b[lb]:
                    # 如果田忌最慢的马 比 齐王最慢的马 快, 则此时田忌最慢的马不是必输的马
                    ans += 200
                    la += 1
                    lb += 1
                else:
                    # 如果田忌最慢的马速度 <= 齐王最慢的马速度, 此时应该让田忌最慢的马 去消耗  齐王最快的马
                    # 如果齐王最快的马速度 > 田忌最慢的马速度,则田忌失去银币
                    # 如果齐王最快的马速度 == 田忌最慢的马速度,则田忌不失去银币
                    if b[rb] > a[la]:
                        ans -= 200
                    la += 1
                    rb -= 1

        print(ans)


# 输入获取
cases = []

while True:
    line = input()

    if line == "0":
        # 算法调用
        getResult(cases)
        break
    else:
        n = int(line)
        a = list(map(int, input().split()))  # 田忌的马速度数组
        b = list(map(int, input().split()))  # 齐王的马速度数组
        cases.append([n, a, b])

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/680987.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1750_使用gcc对嵌入式代码控制逻辑进行测试

全部学习汇总&#xff1a; GreyZhang/c_basic: little bits of c. (github.com) 相信很多人的C语言学习是从printf开始的&#xff0c;为了验证我们的程序代码运行结果&#xff0c;我们通常会选择使用printf打印出我们计算的结果看一下是否与预期一致。到了嵌入式软件开发&#…

web前端工程师个人简历编写(附详细代码)

web前端工程师 h5css3完成简历编写&#xff0c;效果如下&#xff1a; 底部附有详细代码编写 编写Web前端工程师个人简历时&#xff0c;需要注意以下几点&#xff1a; 简洁明了&#xff1a;简历应该简洁明了&#xff0c;内容要点突出&#xff0c;避免冗长和废话。用简洁的语言…

Boost的介绍、安装与环境配置

文章目录 一、Boost库简介二、Boost的安装与编译&#xff08;一&#xff09;下载解压&#xff08;二&#xff09;编译静态库 三、配置VS环境四、其它环境的配置&#xff08;vscode、DevC&#xff09;&#xff08;一&#xff09;在DEVC中配置使用boost库的环境&#xff08;二&am…

java: 程序包javax.servlet.http不存在

问题描述 当项目从2.7.x的springboot升级到3.0.x的时候&#xff0c;遇到一个问题“java: 程序包javax.servlet.http不存在” 。这可能是一些包的精简变化导致的。错误信息如下&#xff1a; 错误代码段 package com.softdev.system.generator.config;import com.softdev.system…

深度学习-ubuntu18.04+RTX3080+cuda11.2+cudnn8.1.0下安装polarstream全纪录

&#xff11;、安装 创建一个python3.7的虚拟环境 conda create --name polarstream python3.7 激活虚拟环境 source activate polarstream以下操作均在虚拟环境中进行 安装与cuda和python版本对应的torch版本,参考https://blog.csdn.net/didadifish/article/details/12748…

【软件设计师暴击考点】操作系统知识高频考点暴击系列【二】

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;软件…

栈的应用——括号匹配、表达式求值、递归

目录 一、栈在括号匹配中的应用逻辑实现代码实现 二、栈在表达式求值中的应用手算实现代码实现 三、栈在递归中的应用逻辑实现代码实现 一、栈在括号匹配中的应用 括号匹配&#xff0c;顾名思义。若括号按照正确的格式嵌套&#xff0c;则可正确匹配&#xff0c;例如([])&#…

scratch lenet(12): LeNet-5输出层和损失函数的计算

文章目录 1. 目的2. 输出层结构2.1 Gaussian Connection2.2 Gaussian Connection 的 weight 可视化 3. Loss Function3.1 当前类别判断错误时&#xff0c;loss function 中的项&#xff08;基本项&#xff09;3.2 判断为其他类别时&#xff0c; loss function 中的项&#xff0…

Spring发展历程及其体系结构

⭐作者介绍&#xff1a;大二本科网络工程专业在读&#xff0c;持续学习Java&#xff0c;努力输出优质文章 ⭐作者主页&#xff1a;逐梦苍穹 ⭐所属专栏&#xff1a;Spring 目录 发展历程体系结构 发展历程 体系结构 Spring框架的体系结构的主要组成部分&#xff1a; 核心容器…

idea如何集成Tomcat

&#xff08;1&#xff09;、这里应该找Add Configuration点击这里&#xff1a;如果没有标志&#xff0c;点击Exit (2)、这里可以配置一个配置项&#xff1a; &#xff08;3&#xff09;、loacl是本地&#xff0c;那个是远程&#xff1a;这里我选择本地 &#xff08;4&#xff…

代码随想录算法训练营第四十二天 | 01背包理论基础,01背包理论基础(滚动数组),416. 分割等和子集

代码随想录算法训练营第四十二天 | 01背包理论基础&#xff0c;01背包理论基础&#xff08;滚动数组&#xff09;&#xff0c;416. 分割等和子集 1.1 01背包理论基础 01背包 回溯法&#xff1a;暴力的解法是o(2^n)指数级别的时间复杂度&#xff0c;需要动态规划的解法来进行优…

如果你曾经拥有python,那么现在你应该拥抱Julia吗?

看完本文&#xff0c;您就会有较成熟的想法。 Julia和Python的区别是什么&#xff1f;为什么Julia适合用于大规模计算和超级计算机模拟&#xff1f; 你一定听说过Julia和Python这两个编程语言。虽然它们都可以用于从简单的机器学习应用程序到巨大的超级计算机模拟的所有方面&am…

Gradio的Audio组件介绍

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

ImGUI项目建立(cmake+MinGW64)

Dear ImGUI ImGui是一个轻量级的C图形界面库&#xff0c;它可以用于创建各种交互式的工具和编辑器。具有跨平台、高性能的特点。 ImGUI自身不能创建窗口&#xff0c;需要使用Win32API或glfw或SDL等工具来创建窗口&#xff0c;另外需要使用OpenGL或DirectX、vulkan用于渲染图形…

excel数据的编排与整理——表格结构的整理(一)

excel数据的编排与整理——表格结构的整理(一) 1 快速移动一列数据到指定位置 1.1 移动到相邻行 1.1.1 题目内容 1.1.2 选中年龄列➡移动到左侧直到出现十字箭头 1.1.3 按下shift键和左键➡移动到指定位置,直到出现"T"字形 1.1.4 松开鼠标左键后,移动就完成了 1.2…

Debian 12中安装Rstudio

1.Debian 12中安装R 打开终端&#xff0c;执行命令&#xff1a;#apt search r-base (注&#xff1a;此图为安装r-base后再来截图的)&#xff0c;Debian 12官方源中默认为r-base 4.2.2,如果想安装最新版&#xff08;当前最新版为R-4.3.0&#xff09;,可参考上次写的博文“Debi…

thinkphp 反序列化漏洞

文章目录 配置xdebug反序列化漏洞利用链详细分析poc1&#xff08;任意文件删除&#xff09;poc2&#xff08;任意命令执行&#xff09; 补充代码 配置xdebug php.ini [Xdebug] zend_extensionD:/phpstudy_pro/Extensions/php/php7.3.4nts/ext/php_xdebug.dll xdebug.modedebu…

Windows系统下安装Hadoop

文章目录 安装步骤环境验证 前面我们已经讲过了在 Linux下安装配置Hadoop环境&#xff0c;还没看过的可以先去了解一下安装流程。今天我们来看一下如何在Window下安装Hadoop&#xff0c;这其实和在Linux下的安装都是大同小异的。下面我们具体来看一下安装步骤。 安装步骤 首先…

pytorch安装教程(Ubuntu22.04.1,Anaconda3-2023.03)

本文主要讲述了在Linux系统中&#xff0c;通过anaconda安装pytorch的具体步骤&#xff0c;即需要在Ubuntu已经安装好anaconda&#xff0c;其安装步骤可以参考此篇博客&#xff1a;Ubuntu安装Anaconda详细步骤&#xff08;Ubuntu22.04.1&#xff0c;Anaconda3-2023.03&#xff0…

数据结构期末总结

数据结构绪论 数据结构的概念 数据结构 &#xff1a; 数据结构是相互之间存在一种或多种特定关系的数据元素的集合数据结构研究的问题 &#xff1a;数据结构是一门研究非数值计算的程序设计问题中计算机的操作对象以及它们之间的关系和操作等的学科抽象数据类型ADT&#xff1a…