python学习——洛谷 [NOIP1998 提高组] 拼数 两种方法

[NOIP1998 提高组] 拼数

题目描述

设有 nnn 个正整数 a1…ana_1 \dots a_na1an,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。

输入格式

第一行有一个整数,表示数字个数 nnn

第二行有 nnn 个整数,表示给出的 nnn 个整数 aia_iai

输出格式

一个正整数,表示最大的整数

样例 #1

样例输入 #1

3
13 312 343

样例输出 #1

34331213

样例 #2

样例输入 #2

4
7 13 4 246

样例输出 #2

7424613

提示

对于全部的测试点,保证 1≤n≤201 \leq n \leq 201n201≤ai≤1091 \leq a_i \leq 10^91ai109

NOIP1998 提高组 第二题

分析

思路来自于排序,常规的排序都是比较两个数的数值的大小,即ab,而在这道题中,我们比较的是两个数拼接(a+bb+a)的大小。
这道题核心在于python中并没有像C/C++能直接自定义sortcomp,而是要先导入functools模块的cmp_to_key的方法,然后再自定义函数。还有一个易错点就是自定义的comp函数不能简单地返回a+b > b+a,而是要根据大于等于小于分别返回-1,0,1才能实现排序效果。

AC代码

from functools import cmp_to_key
def compare(a, b):
    if a+b > b+a:
        return -1
    if a+b < b+a:
        return 1
    return 0

n = input()
nums = list(map(str, input().split()))
nums.sort(key=cmp_to_key(compare))
print(''.join(nums))

在这里插入图片描述

方法2

还有一个思路:
我们发现一般情况下当数值长度越少,高位的数越大,则越应该靠前,但这样不方便比较,因此我们先对数据进行处理,将位数少的数先用0进行补齐,再进行排序比较
在这里插入图片描述
在这里插入图片描述
但这有一个缺陷,就是当数据都补0后如果数值相等,那怎么排序,如下图:
在这里插入图片描述
因此在排序中我们用两个指标,先按补0后的数值排,越大的越靠前,如果补0后数值相等,则按原始数值来排,越小的越靠前。

n = input()
num = [int(x) for x in input().split()]
max_len = len(str(max(num)))
for i in range(len(num)):
    num[i] = [num[i], num[i] * 10 ** (max_len - len(str(num[i])))]
num.sort(key=lambda x:(x[1], -x[0]), reverse=True)
# print(num)
print(int(''.join(str(item[0]) for item in num)))

只能AC大部分数据,有待完善,望大佬指点
在这里插入图片描述

### GP2557 象棋比赛 以下是不使用结构体和 `std::vector` 实现 C++ GP2557 象棋比赛的代码: ```cpp #include <iostream> #include <algorithm> #include <climits> // 计算所有可能的配对合并找出等级差总和最小的安排 void simulateChessTournament(int ratings[], int numPlayers, int numMatches) { int indices[7]; // 假设最多 7 个选手 for (int i = 0; i < numPlayers; ++i) { indices[i] = i; } int minTotalDifference = INT_MAX; int bestIndices[7]; do { int totalDifference = 0; for (int k = 0; k < numMatches; ++k) { int index1 = indices[2 * k]; int index2 = indices[2 * k + 1]; totalDifference += std::abs(ratings[index1] - ratings[index2]); } if (totalDifference < minTotalDifference) { minTotalDifference = totalDifference; for (int i = 0; i < numPlayers; ++i) { bestIndices[i] = indices[i]; } } } while (std::next_permutation(indices, indices + numPlayers)); std::cout << "比赛安排:" << std::endl; for (int k = 0; k < numMatches; ++k) { int index1 = bestIndices[2 * k]; int index2 = bestIndices[2 * k + 1]; std::cout << "第" << k + 1 << "场比赛:选手" << index1 + 1 << " vs 选手" << index2 + 1 << std::endl; // 简单的比赛结果判定,等级高的获胜 if (ratings[index1] > ratings[index2]) { std::cout << "比赛结果:选手" << index1 + 1 << " 获胜" << std::endl; } else { std::cout << "比赛结果:选手" << index2 + 1 << " 获胜" << std::endl; } } } int main() { int ratings[] = {30, 17, 26, 41, 19, 38, 18}; int numPlayers = sizeof(ratings) / sizeof(ratings[0]); int numMatches = numPlayers / 2; simulateChessTournament(ratings, numPlayers, numMatches); return 0; } ``` 上述代码使用普通 `ratings` 存储选手等级信息,`indices` 用于生成所有可能的配对合。通过 `std::next_permutation` 函生成全排列,计算每种配对合下的等级差总和,找到最小等级差总和的配对方案。最后输出每场比赛的安排和简单的比赛结果判定(等级高的选手获胜)。 ### GP2558 NOIP1998 提高问题 问题描述:设有 $n$ 个正整($n \leq 20$),将它们联接成一排,成一个最大的多位整。例如:$n=3$ 时,$3$ 个整 $13$,$312$,$343$,联接成的最大整为:$34331213$。 以下是不使用结构体和 `std::vector` 实现的代码: ```cpp #include <iostream> #include <cstring> #include <algorithm> // 自定义比较函,用于判断两个接后的大小 bool compare(const char* a, const char* b) { char ab[20], ba[20]; strcpy(ab, a); strcat(ab, b); strcpy(ba, b); strcat(ba, a); return strcmp(ab, ba) > 0; } int main() { int n; std::cin >> n; char numbers[20][20]; for (int i = 0; i < n; ++i) { std::cin >> numbers[i]; } // 使用自定义比较函进行排序 std::sort(numbers, numbers + n, compare); // 输出接后的最大整 for (int i = 0; i < n; ++i) { std::cout << numbers[i]; } std::cout << std::endl; return 0; } ``` 上述代码通过自定义比较函 `compare` 来判断两个接后的大小,然后使用 `std::sort` 函对输入的字进行排序,最后将排序后的字依次输出,得到接后的最大整
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qhumaing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值