Codeforces 1181B Split a Number (贪心)
题目大意
把一个数划分成两个没有前导0的正整数,使其和最小。
解题思路
如果不考虑划出来的数有没有前导0的话很好做,为了使划出来的两个数尽量小,一定是要从中间划分的。这里需要注意长度为奇数的时候有两种划法,比如93123,可以化成931+23和93+123。
那么如果从中间划会划出含有前导0的数呢?这样的话中间必定有一串连续的0,我们不能让这些0分开,所以就有了四种划法。设l为距离中间最近的左边的非0的数,r为右边最近的非0的数,那么就可以以l-1, l,r-1,r四个点为分割点(假设分割点划到第一个数里)划分(如果l==r相当于2个划分点)以得到位数最小的答案,然后取最小的答案即可。
代码
string num, s1, s2, ans;
vector<string> ve; int n;
void solve(int cut) {
if (cut<0||cut+1>=n) return;
s1 = num.substr(0, cut+1);
s2 = num.substr(cut+1, n-cut);
if (s2.size()>1&&s2[0]=='0') return;
reverse(s1.begin(),s1.end());
reverse(s2.begin(),s2.end());
int l1 = 0, l2 = 0, carry = 0;
while(l1<s1.size()||l2<s2.size()) {
carry += l1<s1.size() ? s1[l1++]-'0' : 0;
carry += l2<s2.size() ? s2[l2++]-'0' : 0;
ans += carry%10+'0';
carry /= 10;
}
if (carry) ans += carry+'0';
reverse(ans.begin(),ans.end());
ve.push_back(ans); ans.clear();
}
int main() {
cin >> n >> num;
int l = n/2, r = n/2;
while(num[l]=='0') --l;
while(r<n&&num[r]=='0') ++r;
solve(l); solve(l-1);
solve(r-1); solve(r);
sort(ve.begin(),ve.end(),[](string a, string b) {
return a.size()==b.size() ? a<b : a.size()<b.size();
});
cout << ve[0] << endl;
return 0;
}