题目描述
A,B两个人玩一个数字比大小Q的游戏,在游戏前,两个人会拿到相同长度的两个数字序列,两个数字序列不相同的且其中的数字是随机的。A,B各自从数字序列中挑选出一个数字进行大小比较,赢的人得1分,输的人扣1分,相等则各自的分数不变。用过的数字需要丢弃。求A可能赢B的最大分数
输入描述
输入数据的第1个数字表示数字序列的长度N,后面紧跟着两个长度为N的数字序列,
输出描述
A可能赢B的最大分数
备注
1.这里要求计算A可能赢B的最大分数,不妨假设,A知道B的数字序列,且总是B先挑选数字并明示
2.可以采用贪心策略,能赢的一定要赢,要输的尽量减少损失。
示例1
输入
3
4 8 10
3 6 4
输出
3
说明
输入数据第1个数字表示数字序列长度为3,后面紧跟着两个长度为3的数字序列。
序列A: 4 8 10
序列B: 3 6 4
A可以赢的最大分数是3。获得该分数的比大小过程可以是:
-
A: 4 B: 3
-
A: 8 B: 6
-
A: 10 B: 4
思路
此游戏是让 A 和 B 从各自的数字序列里挑选数字进行比较,比大小后计分,用过的数字要丢弃,目标是算出 A 可能赢 B 的最大分数。核心思路为对 A 和 B 的数字序列排序,然后让 A 的数字尽可能地去战胜 B 的数字,要是无法战胜,就用 A 的最小数字去 “消耗” B 的最大数字。
Java
import java.util.*;
public class Main2 {
public static void main(String[] args) {
// 创建一个Scanner对象用于读取输入
Scanner sc = new Scanner(System.in);
// 读取数字序列的长度
int n = sc.nextInt();
// 存储A的数字序列
List<Integer> up = new ArrayList<>();
// 存储B的数字序列
List<Integer> down = new ArrayList<>();
// 读取A的数字序列
for (int i = 0; i < n; i++) {
up.add(sc.nextInt());
}
// 读取B的数字序列
for (int i = 0; i < n; i++) {
down.add(sc.nextInt());
}
// 对A的数字序列进行排序
Collections.sort(up);
// 对B的数字序列进行排序
Collections.sort(down);
// 初始化A的最大得分
int mx = 0;
// 标记B的数字是否已使用,初始化为0表示未使用
List<Integer> use = new ArrayList<>(Collections.nCopies(n, 0));
// 遍历A的数字序列
for (int i : up) {
// 记录B中小于i的最大数字的索引
int x = -1;
// 记录B中最大未使用数字的索引
int p = -1;
// 从后往前遍历B的数字序列
for (int j = n - 1; j >= 0; --j) {
if (use.get(j) != 1) {
// 更新最大未使用数字的索引
p = Math.max(p, j);
if (i > down.get(j)) {
// 找到小于i的数字,记录其索引
x = j;
break;
}
}
}
if (x == -1) {
// 未找到小于i的数字,用i去“消耗”B的最大未使用数字
use.set(p, 1);
// 若B的数字大,A得分减1
mx -= down.get(p) > i ? 1 : 0;
continue;
}
// 找到小于i的数字,A得分加1
use.set(x, 1);
mx += 1;
}
// 输出A可能赢B的最大分数
System.out.println(mx);
}
}
Python3
# 读取输入的数字序列长度
n = int(input())
# 读取A的数字序列
up = list(map(int, input().split()))
# 读取B的数字序列
down = list(map(int, input().split()))
# 对A的数字序列进行排序
up.sort()
# 对B的数字序列进行排序
down.sort()
# 初始化A的最大得分
mx = 0
# 标记B的数字是否已使用,初始化为False表示未使用
use = [False] * n
# 遍历A的数字序列
for i in up:
# 记录B中小于i的最大数字的索引
x = -1
# 记录B中最大未使用数字的索引
p = -1
# 从后往前遍历B的数字序列
for j in range(n - 1, -1, -1):
if not use[j]:
# 更新最大未使用数字的索引
p = max(p, j)
if i > down[j]:
# 找到小于i的数字,记录其索引
x = j
break
if x == -1:
# 未找到小于i的数字,用i去“消耗”B的最大未使用数字
use[p] = True
# 若B的数字大,A得分减1
mx -= 1 if down[p] > i else 0
continue
# 找到小于i的数字,A得分加1
use[x] = True
mx += 1
# 输出A可能赢B的最大分数
print(mx)
C++
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
// 读取数字序列的长度
cin >> n;
// 存储A的数字序列
vector<int> up(n);
// 存储B的数字序列
vector<int> down(n);
// 读取A的数字序列
for (int i = 0; i < n; i++) {
cin >> up[i];
}
// 读取B的数字序列
for (int i = 0; i < n; i++) {
cin >> down[i];
}
// 对A的数字序列进行排序
sort(up.begin(), up.end());
// 对B的数字序列进行排序
sort(down.begin(), down.end());
// 初始化A的最大得分
int mx = 0;
// 标记B的数字是否已使用,初始化为0表示未使用
vector<int> use(n, 0);
// 遍历A的数字序列
for (int i : up) {
// 记录B中小于i的最大数字的索引
int x = -1;
// 记录B中最大未使用数字的索引
int p = -1;
// 从后往前遍历B的数字序列
for (int j = n - 1; j >= 0; --j) {
if (use[j] != 1) {
// 更新最大未使用数字的索引
p = max(p, j);
if (i > down[j]) {
// 找到小于i的数字,记录其索引
x = j;
break;
}
}
}
if (x == -1) {
// 未找到小于i的数字,用i去“消耗”B的最大未使用数字
use[p] = 1;
// 若B的数字大,A得分减1
mx -= down[p] > i ? 1 : 0;
continue;
}
// 找到小于i的数字,A得分加1
use[x] = 1;
mx += 1;
}
// 输出A可能赢B的最大分数
cout << mx << endl;
return 0;
}
C语言
#include <stdio.h>
#include <stdlib.h>
// 比较函数,用于qsort排序
int cmp(const void *a, const void *b) {
return (*(int *)a - *(int *)b);
}
int main() {
int n;
// 读取数字序列的长度
scanf("%d", &n);
// 存储A的数字序列
int *up = (int *)malloc(n * sizeof(int));
// 存储B的数字序列
int *down = (int *)malloc(n * sizeof(int));
// 读取A的数字序列
for (int i = 0; i < n; i++) {
scanf("%d", &up[i]);
}
// 读取B的数字序列
for (int i = 0; i < n; i++) {
scanf("%d", &down[i]);
}
// 对A的数字序列进行排序
qsort(up, n, sizeof(int), cmp);
// 对B的数字序列进行排序
qsort(down, n, sizeof(int), cmp);
// 初始化A的最大得分
int mx = 0;
// 标记B的数字是否已使用,初始化为0表示未使用
int *use = (int *)calloc(n, sizeof(int));
// 遍历A的数字序列
for (int i = 0; i < n; i++) {
// 记录B中小于up[i]的最大数字的索引
int x = -1;
// 记录B中最大未使用数字的索引
int p = -1;
// 从后往前遍历B的数字序列
for (int j = n - 1; j >= 0; --j) {
if (use[j] != 1) {
// 更新最大未使用数字的索引
p = (p > j) ? p : j;
if (up[i] > down[j]) {
// 找到小于up[i]的数字,记录其索引
x = j;
break;
}
}
}
if (x == -1) {
// 未找到小于up[i]的数字,用up[i]去“消耗”B的最大未使用数字
use[p] = 1;
// 若B的数字大,A得分减1
mx -= (down[p] > up[i]) ? 1 : 0;
continue;
}
// 找到小于up[i]的数字,A得分加1
use[x] = 1;
mx += 1;
}
// 输出A可能赢B的最大分数
printf("%d\n", mx);
// 释放动态分配的内存
free(up);
free(down);
free(use);
return 0;
}
JsNode
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 读取输入的数字序列长度
rl.question('', (n) => {
n = parseInt(n);
// 读取A的数字序列
rl.question('', (upInput) => {
const up = upInput.split(' ').map(Number);
// 读取B的数字序列
rl.question('', (downInput) => {
const down = downInput.split(' ').map(Number);
// 对A的数字序列进行排序
up.sort((a, b) => a - b);
// 对B的数字序列进行排序
down.sort((a, b) => a - b);
// 初始化A的最大得分
let mx = 0;
// 标记B的数字是否已使用,初始化为false表示未使用
const use = new Array(n).fill(false);
// 遍历A的数字序列
for (let i of up) {
// 记录B中小于i的最大数字的索引
let x = -1;
// 记录B中最大未使用数字的索引
let p = -1;
// 从后往前遍历B的数字序列
for (let j = n - 1; j >= 0; --j) {
if (!use[j]) {
// 更新最大未使用数字的索引
p = Math.max(p, j);
if (i > down[j]) {
// 找到小于i的数字,记录其索引
x = j;
break;
}
}
}
if (x === -1) {
// 未找到小于i的数字,用i去“消耗”B的最大未使用数字
use[p] = true;
// 若B的数字大,A得分减1
mx -= down[p] > i ? 1 : 0;
continue;
}
// 找到小于i的数字,A得分加1
use[x] = true;
mx += 1;
}
// 输出A可能赢B的最大分数
console.log(mx);
rl.close();
});
});
});
Go
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// 读取数字序列的长度
scanner.Scan()
n, _ := strconv.Atoi(scanner.Text())
// 存储A的数字序列
var up []int
// 存储B的数字序列
var down []int
// 读取A的数字序列
scanner.Scan()
upInput := strings.Split(scanner.Text(), " ")
for _, numStr := range upInput {
num, _ := strconv.Atoi(numStr)
up = append(up, num)
}
// 读取B的数字序列
scanner.Scan()
downInput := strings.Split(scanner.Text(), " ")
for _, numStr := range downInput {
num, _ := strconv.Atoi(numStr)
down = append(down, num)
}
// 对A的数字序列进行排序
sort.Ints(up)
// 对B的数字序列进行排序
sort.Ints(down)
// 初始化A的最大得分
mx := 0
// 标记B的数字是否已使用,初始化为false表示未使用
use := make([]bool, n)
// 遍历A的数字序列
for _, i := range up {
// 记录B中小于i的最大数字的索引
x := -1
// 记录B中最大未使用数字的索引
p := -1
// 从后往前遍历B的数字序列
for j := n - 1; j >= 0; j-- {
if!use[j] {
// 更新最大未使用数字的索引
if j > p {
p = j
}
if i > down[j] {
// 找到小于i的数字,记录其索引
x = j
break
}
}
}
if x == -1 {
// 未找到小于i的数字,用i去“消耗”B的最大未使用数字
use[p] = true
// 若B的数字大,A得分减1
if down[p] > i {
mx--
}
continue
}
// 找到小于i的数字,A得分加1
use[x] = true
mx++
}
// 输出A可能赢B的最大分数
fmt.Println(mx)
}