题目描述:
1097 拼成最小的数
设有n个正整数,将它们联接成一排,组成一个最小的多位整数。
例如:
n=2时,2个整数32,321连接成的最小整数为:32132,
n=4时,4个整数55,31,312, 33 联接成的最小整数为:312313355
收起
输入
第1行:1个数N。(2 <= N <= 10000) 第2 - N + 1行:每行1个正整数。(1 <= A[i] <= 10^9)
输出
输出拼在一起的最小整数。由于数据量太大,请以1000个字符为单位,输出到一行里, 最终剩余的不足1000个字符的部分,输出到单独1行。
输入样例
4 55 31 312 33
输出样例
312313355
思路:
刚开始,考虑先将所有排序,比较难处理的地方就是一串是另一个串的子串,这种情况下,
长的肯定在后面,然后什么情况家要把长串的移动到前面,即短串加上长的串,这样的思路是
不对的,具体为什么,不得而知,只知道有特殊样例过不了。
正确的思路是:
交换相邻两个串a,b会使答案变差当且仅当a+b<b+a,
(下面没看懂... ...)
用num(s)表示s对应的十进制数,
则有num(a)*10^|b|+num(b)<num(b)*10^|a|+num(a),
整理一下可得num(a)/(10^|a|-1)<num(b)/(10^|b|-1),
即自定义cmp函数为: S1+S2<S2+S1;
代码实现:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
typedef long long ll;
const int N=2e5+20;
const int M=30;
string str[N];
bool cmp(string s1,string s2)
{
return s1+s2<s2+s1;
}
int main()
{
int n;
while(cin>>n)
{
for(int i=1;i<=n;i++)cin>>str[i];
sort(str+1,str+1+n,cmp);
string ans="";
for(int i=1;i<=n;i++)ans+=str[i];
int cnt=0;
for(int i=0;i<ans.length();i++)
{
cout<<ans[i];
cnt++;
if(cnt==1000)
{
cnt=0;
cout<<endl;
}
}
if(cnt!=1000)cout<<endl;
}
return 0;
}
刚开始水过的代码,没有啥依据,瞎几把写:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N=2e5+100;
struct String
{
string s;
int len;
}str[N];
bool cmp(String s1,String s2)
{
return s1.s<s2.s;
}
string ans;
int main()
{
int n;
while(cin>>n)
{
ans="";
for(int i=1;i<=n;i++)cin>>str[i].s,str[i].len=str[i].s.length();
sort(str+1,str+1+n,cmp);
for(int i=1;i<n;i++)str[i].s+=str[i+1].s; //****无依据,瞎写
sort(str+1,str+1+n,cmp);
for(int i=1;i<=n;i++)ans+=str[i].s.substr(0,str[i].len);
int cnt=0;
int leng=ans.length();
for(int i=0;i<leng;i++)
{
cout<<ans[i];
cnt++;
if(cnt==1000)cout<<endl,cnt=0;
}
cout<<endl;
}
return 0;
}
The end;