P1012 [NOIP1998 提高组] 拼数题解

题目

设有n个正整数a_{1},a_{2},\cdots ,a_{n},将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。

输入输出格式

输入格式

第一行有一个整数,表示数字个数n。

第二行有n个整数,表示给出的n个整数a_{i}

输出格式

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

输入输出样例

输入样例

3
13 312 343

输出样例

34331213

代码

#include
#include
using namespace std;
struct node{
	string s;
}a[25];
int n;
bool cmp(node x,node y){
	if(x.s+y.s>y.s+x.s){
		return 1;
	}
	return 0;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i].s;
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		cout<

解析

我们先定义几个符号,ab(a,b是数字字符串)表示a+b也就是把a和b连起来写

abc(a,b,c都是数字符串)(当然再多几个字符串也没关系,跟上面一个意思)

a⩾b 表示正常的a大于等于b
a>=b a,b是数字字符串 表示a+b⩾b+a    注意区分这两个大于等于!

a*n a是数字字符串,n是正整数,表示把a连续写n遍形成的很长的字符串

下面开始证明。

从代码中可以看出,我们把a数组按这个 >= 符号降序排好序,再直接输出就是正确的答案了。容易发现,对于任意一种排列方式,只要相邻的两个数满足前面的>=后面的,那么这种排列肯定不是最优的。也就是说,对于最优排列,肯定有第一个串>=第二个串,第二个串>=第三个串,第三个串>=第四个串 ... 依此类推。

经过这一些简单的推理,证明的思路实际上很清晰了:只需要再证明传递性(由a>=bb>=c 能否推出a>=c)。这是最后的一步,也是关键的一步。

先证明一个性质: 如果a>=b,那么a*n>= b。 (思路:递推/数学归纳法)

a>=b即ab⩾ba,可知aab⩾aba并且aba⩾baa,从而aab⩾baa也就是a*2>=b

a*2>=b即aab⩾baa 又由ab⩾ba,可知aaab⩾abaa并且abaa⩾baaa

从而aaab⩾baaa,也就是 a*3>=b,依此类推,便能证得a*n>=b
类似地,由a>=b,也可以得到a>=b*n。 相反,如果a*n>=b或者a>=b*n,也能得到 a>=b

有了这个结论,我们只要a,b,c各乘上一个合适的整数,不难证明传递性了。

你可能感兴趣的:(贪心算法专题,排序算法专题,算法,c++)