1038. Recover the Smallest Number (30)
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 (<=10000) 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. Do not output leading zeros.
Sample Input:5 32 321 3214 0229 87Sample Output:
22932132143287
很明显这是一道排序题,这道题的学问主要在排序函数,不能使用通常的字符串比较函数,例如实例中,当32,321,3214这3个数同时存在于序列中时,如何决定这三个数的顺序,可以肯定的是,当多个数有相同的前缀时,这几个数出现时一定是相邻的,如结果中的321 32 3214,方法就是当比较两个字符串大小时如32和321,如果有相同前缀,则删除较长的字符串中的前缀,并比较剩下的数的大小,即32和321的比较结果应该是32和1的比较结果,同理,321和3214的比较结果应该是321和4的比较结果,3214和32的比较结果应该等于14和32的比较结果,代码如下:
本题目的另外一个坑点就是当所有的数都是0的时候,去除前导的0可能会使得整个数都被剪裁没了,此时要进行特判,否则可能会发生“异常退出”的情况
#include<iostream> #include<vector> #include<algorithm> #include<string> using namespace std; vector<string> num; bool cmp(string a, string b){ int len[2]; len[0] = a.length(), len[1] = b.length(); int i = 0; while (i < len[0] && i < len[1]){ if (a[i] < b[i]) return true; else if (a[i] > b[i]) return false; else; i++; } if (i < len[0]) return cmp(a.substr(i),b); else if (i < len[1]) return cmp(a,b.substr(i)); else return true;//两个数完全相同 } int main(){ string temp, ans; int n,k; cin >> n; vector<string>::iterator it; while (n--){ cin >> temp; num.push_back(temp); } sort(num.begin(), num.end(), cmp); it = num.begin(); while (it != num.end()){ ans += *it; it++; } if ((k = ans.find_first_not_of('0')) != string::npos)//如果整个数都是0 ans = ans.substr(k); else ans = "0"; cout << ans << endl; return 0; }