POJ - 2287 Tian Ji -- The Horse Racing

Topic source

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

topic description

Tian Ji's horse race is a famous story in Chinese history.

This story happened 2300 years ago. Tian Ji was a high official in Qi State. He liked to race horses with King Qi and other princes.

Both Tian Ji and the king of Qi have three types of horses, which are low-grade horses, middle-grade horses, and high-grade horses.

There are three rounds in total, and each horse can only be used in one round. The winner of each round can get 200 silver coins from the loser.

King Qi is the most powerful man in Qi, so his horses are very good, and every level of horse is better than Tian Ji's horse of the same level. Therefore, Tian Ji would lose 600 silver coins to King Qi every time.

Tian Ji was very distressed by this until he met Sun Bin, one of the most famous military advisers in Chinese history. Sun Bin provided Tian Ji with the following strategy, allowing Tian Ji to win back 200 silver coins in the next game. This is a very simple strategy, namely:

  • Tian Ji's low-grade horse vs. the monarch's high-grade horse (Tian Ji loses and loses 200 silver coins)
  • Tian Ji's middle horse vs the monarch's low horse (Tian Ji wins and gets 200 silver coins)
  • Tian Ji's high-quality horse vs. the monarch's medium-sized horse (Tian Ji wins and gets 200 silver coins)

In fact, the above horse racing problem can be simply regarded as: finding the maximum matching in the bipartite graph.

Draw Tian Ji's horse on one side and King Qi's horse on the other side.

As long as Tian Ji's horse can beat Qi Wang's horse, we will draw a connecting line between the two horses, indicating that we want the two horses to compete in a match.

Then, Tian Ji wins as many rounds as possible, in fact, it is to find the largest match in this graph.

If there is a tie, then the problem becomes more complicated, he needs to assign weights 0, 1 or -1 to all possible variants and find a maximum weighted perfect match.

Then, the horse racing problem is a very special bipartite graph matching problem. This graph is determined by the speed of the horse. Faster vertices always outperform slower ones. In this case, the weighted bipartite graph matching algorithm seems a bit overkill.

Please design an algorithm to solve this special matching problem.

enter description

Enter up to 50 sets of use cases.

Each set of use cases:

  • The first row is an integer n (n ≤ 100) indicating the number of horses in each side.
  • The second line is n integers, indicating the speed of Tian Ji's horse.
  • The third line is n integers, indicating the speed of King Qi's horse.

The end condition of the input is to enter a line with only '0' after the last set of cases.

output description

Output one line for each set of use cases, and each line contains an integer, indicating the maximum number of silver coins that Tian Ji can obtain under this set of use cases.

Example

enter 3
92 83 71
95 87 74
2
20 20
20 20
2
20 19
22 18
0
output 200
0
0
illustrate none

topic analysis

This question can be solved using greedy thinking.

That is: if Tian Ji wants to get the most silver coins, he should let Tian Ji lose the least, so how to make Tian Ji lose the least?

That is to use Tian Ji's "must lose" and "slowest" horse to consume King Qi's fastest horse.

Therefore, we need to sort the horses of Tian Ji and King Qi in ascending order first, so that we can find the slowest and fastest horses.

  • If Tian Ji's fastest horse > King Qi's fastest horse, Tian Ji wins this round
  • If Tian Ji's fastest horse < King Qi's fastest horse, Tian Ji will lose this round, but in order to keep Tian Ji's fastest horse, we should let Tian Ji take out the slowest horse in the race, so that the race will be at the least cost lose.
  • If the condition of the fastest horse == King Qi's fastest horse, Tian Ji will draw this round, but the price is indeed lost. At this time, we should consider finding a horse that must lose from Tian Ji's horse and The slowest horse consumes King Qi's fastest horse. Although he lost this round, Tian Ji just lost the horse that must lose in advance. The advantage is that he kept the fastest horse. So next we should find the slowest horse that Tian Ji will lose.
  1. If Tian Ji's slowest horse > King Qi's slowest horse, then the current Tian Ji's slowest horse is not the slowest horse that Tian Ji will lose, and we should continue to look for
  2. If Tian Ji's slowest horse < King Qi's slowest horse, then Tian Ji's slowest horse is the slowest horse that Tian Ji will lose, and we should race this horse against King Qi's fastest horse
  3. If Tian Ji's slowest horse == King Qi's slowest horse, then the current Tian Ji's slowest horse is not the slowest horse that Tian Ji must lose, we should continue to search

JS algorithm source code

/* 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 algorithm source code

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 algorithm source code

# 算法入口
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])

Guess you like

Origin blog.csdn.net/qfc_128220/article/details/131360280