第一题:T1连接数字
标签:字符串、贪心
题意:给定
n
n
n个十进制正整数
a
1
,
a
2
,
…
,
a
n
a_1,a_2,…,a_n
a1,a2,…,an,将它们重新排列后拼接起来,尽可能地变成一个大数字,输出这个巨大的数字。
(
1
<
=
n
<
=
100000
,
1
<
=
a
i
<
=
1
0
18
)
(1<=n<= 100000,1<=a_i<=10^{18})
(1<=n<=100000,1<=ai<=1018)
题解:洛谷 P1012 拼数(原题),很明显需要给这个序列重新排序,然后输出这个序列。那问题就转变成了,需要按什么规则进行排序,这里需要想一个好的贪心策略。
- 假设按数字大小从大到小排序,很明显能举出一个反例: 111 、 9 111、9 111、9; 1119 < 9111 1119 < 9111 1119<9111
- 到这步能比较容易想到以字符串的方式读入,似乎更可行点。按字符串字典序从大到小排序,上面是满足了,但是也能举出反例: 32 、 3 32、3 32、3; 323 < 332 323<332 323<332。因为字符串比较,如果能比较的位都一样,认为长的字符串字典序大。
- 然后我们发现题目中更像是拼接的形式,我们会去考虑把两个字符串 a + b a+b a+b拼接,或者 b + a b+a b+a拼接,然后进行比较大小,发现上面的反例都能满足。那我们就认为该贪心策略是对的。贪心策略是否是正确的,很多时候都很难去证明,我们想一道题的贪心策略的时候,多举反例,只要有一个反例,那你当前想的这个策略就是错的,需要想新的贪心策略。(类似 1 、 2 1、2 1、2)
代码:
#include <bits/stdc++.h>
using namespace std;
int n;
string s[100005];
bool cmp(string a, string b) {
return a + b > b + a;
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> s[i];
sort(s + 1, s + 1 + n, cmp);
for (int i = 1; i <= n; i++) cout << s[i];
return 0;
}