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;
}
原文地址:https://www.cnblogs.com/shuitiangong/p/12944560.html