问题描述
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.
解决方法
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
vector<string> v;
//判断字符串有多少前导零
int calcZero(string s)
{
int n = 0;
for (int i = 0; i < s.length(); i++)
{
if (s[i] != '0')
break;
n++;
}
return n;
}
//核心比较函数
bool cmp(string s1, string s2)
{
int pre1 = calcZero(s1);
int pre2 = calcZero(s2);
//前导0多的放前面
if (pre1 != pre2)
{
return pre1 > pre2;
}
else
{
int len1 = s1.length();
int len2 = s2.length();
//长度相同的比较大小
if (len1 == len2)
{
return s1 < s2;
}
/* 长度不相等的 先看短的字符串和长的相同长度的前缀比较大小,要小的在前。
如果比较结果相等就通过拼接比较来判断那个应该排在前。
*/
else if (len1 > len2)
{
//相同长度的前缀比较
if (s1.substr(0, len2) != s2)
{
return s1.substr(0, len2) < s2;
}
//拼接比较先后顺序
else
{
return s1.substr(len2) + s2 < s1;
}
}
else
{
//相同长度的前缀比较
if (s2.substr(0, len1) != s1)
{
return s2.substr(0, len1) > s1;
}
//拼接比较先后顺序
else
{
return s2.substr(len1) + s1 > s2;
}
}
}
}
int main(void)
{
//输入数据并排序
int m;
string str = "";
scanf("%d", &m);
for (int i = 0; i < m; i++)
{
string s;
cin >> s;
v.push_back(s);
}
sort(v.begin(), v.end(), cmp);
//根据排序结果 拼接字符串str
for (vector<string>::iterator it = v.begin(); it != v.end(); it++)
{
str += *it;
}
//清除结果的前导0,如果导致结果为空则要输出0 测试用例2就是这样的情形
int begin = calcZero(str);
str = str.substr(begin);
if (str.length() == 0)
{
cout << 0 << endl;
}
else
{
cout << str << endl;
}
return 0;
}
基本策略(cmp)
- 先按前导零个数选择顺序尽量减少位数和将0放在高位
- ,前导零个数相同的长度相等的按字典序比较小的放前面
- 长度不同的如s1>s2,先从s1前缀中截取s2长度的字符串比较小的放前面
- 如果比较还相等就将s1剩余部分+s2来和s1本身比较确定顺序。(s1s2,s2s1)
遇到的问题
- 本来挺有自信的但是测试用例2总报错,才发现当拼接出的字符串全为0时结果会为空
结果展示
PatA1038.png