[NOIP1998 提高组] 拼数

题目描述

设有 $n$ 个正整数 $a_1 \dots a_n$,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。

输入格式

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

第二行有 $n$ 个整数,表示给出的 $n$ 个整数 $a_i$。

输出格式

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

样例 #1

样例输入 #1

1
2
3
13 312 343

样例输出 #1

1
34331213

样例 #2

样例输入 #2

1
2
4
7 13 4 246

样例输出 #2

1
7424613

提示

对于全部的测试点,保证 $1 \leq n \leq 20$,$1 \leq a_i \leq 10^9$。

解题思路

先比较最高位数,若最高位数相等,再比较下一位,考虑到两数位数不同的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
for(i=0;i<n-1;i++){
for(j=n-1;j>i;j--){
p=a[j];
q=a[j-1];
while((q/10!=0||q%10!=0)&&(p/10!=0||p%10!=0)){
if(begin(p)>begin(q)){
x=a[j];
a[j]=a[j-1];
a[j-1]=x;
break;
}
else if(begin(p)==begin(q)){
q=lose(q);
p=lose(p);
}
else if(begin(p)<begin(q)){
break;
}
}
if((q==0&&begin(p)>begin(a[i]))||(p==0&&begin(q)<begin(a[i-1]))){
x=a[j];
a[j]=a[j-1];
a[j-1]=x;
}
}
}

代码展示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include<stdio.h>
#define N 20
int begin(int a);
int len(int a);
int lose(int a);
int main()
{
int n,i,j,x,p,q;
long num;
int a[N]={0};
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(i=0;i<n-1;i++){
for(j=n-1;j>i;j--){
p=a[j];
q=a[j-1];
while((q/10!=0||q%10!=0)&&(p/10!=0||p%10!=0)){
if(begin(p)>begin(q)){
x=a[j];
a[j]=a[j-1];
a[j-1]=x;
break;
}
else if(begin(p)==begin(q)){
q=lose(q);
p=lose(p);
}
else if(begin(p)<begin(q)){
break;
}
}
if((q==0&&begin(p)>begin(a[i]))||(p==0&&begin(q)<begin(a[i-1]))){
x=a[j];
a[j]=a[j-1];
a[j-1]=x;
}
}
}
for(i=0;i<n;i++){
printf("%d",a[i]);
}
return 0;
}
int begin(int a)
{
int i,x=1;
for(i=1;i<len(a);i++){
x=x*10;
}
return a/x;//整数的最高位的值
}
int len(int a)
{
int x=1;
while(a/10>0){
a=a/10;
x++;
}
return x;//整数的位数
}
int lose(int a)
{
int i,x=1;
for(i=1;i<len(a);i++){
x=x*10;
}
return a%x;//整数去掉最高位的值
}