原题
Given a collection of number segments, you are supposed to recover the smallest number from them. For example, given { 32, 321, 3214, 0229, 87 }, we can recover many numbers such like 32-321-3214-0229-87 or 0229-32-87-321-3214 with respect to different orders of combinations of these segments, and the smallest number is 0229-321-3214-32-87.
Input Specification:
Each input file contains one test case. Each case gives a positive integer N (≤104) followed by N number segments. Each segment contains a non-negative integer of no more than 8 digits. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the smallest number in one line. Notice that the first digit must not be zero.
Sample Input:
5 32 321 3214 0229 87
结尾无空行
Sample Output:
22932132143287
结尾无空行
思路
把输入的数据(除了第一项)以字符串读入,再按字典序(特殊情况特殊处理)排序了再输出。
通过代码
#include <bits/stdc++.h>
#include <string>
using namespace std;
vector<string> str(10001);
bool cmp(string a,string b){
return a+b<b+a;
}
int main(){
string result;
int n;
cin>>n;
for(int i=0;i<=n-1;i++){
cin>>str[i];
}
sort(str.begin(),str.begin()+n,cmp);
for(int i =0 ;i<=n-1;i++){
result+=str[i];
}
while(result[0]=='0'){
result.erase(result.begin()+0);
}
if(result.empty()){
cout<<'0';
}
else{
cout<<result;
}
return 0;
}
总结
知识
1.vector的用法,见https://blog.csdn.net/qq_45520030/article/details/119837736?spm=1001.2014.3001.5501
2.string的理解,总结地点同上。
方法
1.一开始对“0”的处理有问题,最先只删除了一个结尾开头可能出现的‘0’,后来发现可能不止有一个‘0’就重写代码删到不为‘0’为止,却又忽略了全是‘0’的情况下需要输出一个‘0’。以后考虑极限情况时请假设“没有xx怎么办”,“有不止一个xx怎么办”,“全是xx怎么办”。
2.一开始忽略了这道题中不是所有字符串都应该按字典序排序,例如“32”和“32103”,按字典序排列“32更小”,但是如果把“32”排在前面,“3232103”明显比“3210332”要大。
意识到这一点之后我想的是在比较两个数a、b时先比较长度重合的部分,如果长度重合的部分相等,再将更长的一方超出的部分和短的一方比较,例如上例先比较“32”和“32”相等再比较“32”和“103”,明显“103”更小所以将“32103”放在更靠前的位置。自认为思路没有问题,但老是有一个测试用例通不过(sort函数的cmp参数代码如下(看着复杂的还有一个原因是没有用string))。
bool cmp(char a[],char b[]){
int an=strlen(a),bn=strlen(b);
int special=0;
if(an>bn){
return (!cmp(b,a));
}
else if(an<bn){
for(int i=0;i<an;i++){
if(a[i]!=b[i]) {
special=0;
break;
}
special=1;
}
if(special){
for(int i=an,j=0;i<bn;i++,j++){
if(a[j]>b[i]){
return false;
}
}
}
}
return (string)a<(string)b;
}
看了其他朋友的代码,发现了简单得多的方法,即直接比较a+b和b+a谁大就好。
bool cmp(string a,string b){
return a+b<b+a;
}
下次遇上类似情况,请先在草稿纸下写下来目的是什么,写代码之前根据目的想想有没有简单方法。
3.我一直是把数字作为字符串在处理,但是一开始写判断语句时,却又拿0在作比较,以后一定要注意究竟应该用数字还是字符串。
心态
看到以为简单的题别得意(敲头三下呜呜)。