[NOIP1998 提高组] 拼数
题目描述
设有 n n n 个正整数 a 1 … a n a_1 \dots a_n a1…an,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。
输入格式
第一行有一个整数,表示数字个数 n n n。
第二行有 n n n 个整数,表示给出的 n n n 个整数 a i a_i ai。
输出格式
一个正整数,表示最大的整数
样例 #1
样例输入 #1
3
13 312 343
样例输出 #1
34331213
样例 #2
样例输入 #2
4
7 13 4 246
样例输出 #2
7424613
提示
对于全部的测试点,保证 1 ≤ n ≤ 20 1 \leq n \leq 20 1≤n≤20, 1 ≤ a i ≤ 1 0 9 1 \leq a_i \leq 10^9 1≤ai≤109。
NOIP1998 提高组 第二题
思路
把待拼接的整数看作字符串,比较拼接之后的字典序,字典序大的,拼接得到的整数就大。即有两个字符串a
和b
,如果a + b > b + a
,那么a
就排在前。
证明(如有错误烦请指出!)
这里尝试证明一下,感觉有点像贪心证明。假设按照上面这种拼接方式(任意相邻两个数都满足这样的排序方式)得到的是一个可行解ans
,最优解为max
,那么ans <= max
。
现在交换max
中的相邻两个不按这种排序方式排序的两个整数a
,b
,即原来a + b < b + a
,但a
排在前。交换后一定能够使整个拼接的数变大(因为不改变其他数的位置),反复这样交换,就能把max
变为ans
,而数的大小不减,由此证出max <= ans
。
综上,ans == max
。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#define endl '\n'
using namespace std;
const int N = 30;
int n;
string a[N];// 用字符串来存储每个整数,便于之后拼接
bool cmp(string a, string b) {
return a + b > b + a;// 比较拼接之后的字典序,字典序大的,拼接得到的整数就大
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
sort(a, a + n, cmp);
for (int i = 0; i < n; i++) {
cout << a[i];
}
cout << endl;
return 0;
}