Codeforces Round #350 (Div. 2) F. Restore a Number(贪心构造)★ ★ ★

题目大意:

给定一组数字字符串,其中包含一个大数和大数的长度,且这些数字被随机存储

第二行为大数包含的子数列
求出这个大数能够得到的最小数

题解:

首先求出大数的长度

len为数字字符串的长度,digits从0递增判断(len-digits)的位数+(len-digits)是否与len相等
求出大数的长度
接着求最小数
方法一(有些复杂):
把整个数列分成3部分子数列前pre,子数列,子序列后

基本上是贪心加特殊处理。

#include <cstdio>
#include <set>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
int cnt[13];
string s;
string remaind, tt;
int len, ll;
int main()
{
    cin>> s;
    cin>>tt;
    int len = s.length();
    int n = 0;
    ll = 0;
    if (len == 2)
    {
        cout << tt << endl;
        return 0;
    }
    for (int i = 0; i < 10; i++)
    {
        cnt[i] = 0;
    }
    for (int i = 0; i < len; i++)
    {
        cnt[s[i]-'0']++;
    }
    int t = len-1;
    int digits = 1;
    int dt;
    int f = t;
    dt = 0;
    while (f > 0)
    {
        f/=10;
        dt++;
    }
    while (t+dt != len)
    {
        digits++;
        t = len-digits;
        int f = t;
        dt = 0;
        while (f > 0)
        {
            f/=10;
            dt++;
        }
    }
    len = t;
    while (t)
    {
        cnt[t%10]--;
        t /= 10;
    }
    int firstt = tt[0]-'0', flag = 0, mintt = 1;
    for (int i = 0; i < tt.length(); i++)
    {
        cnt[tt[i]-'0']--;
        if (i != 0 && !flag)
        {
            if (tt[i]-'0' < firstt)
            {
                flag = 1;
                mintt = tt[i]-'0';
            }
            else if (tt[i]-'0' > firstt)
                flag = 2;
        }
    }
    int countzero = 0;
    if (mintt == 0)
    {
        int flagg = 0;
        for (int i = 0; i < tt.length(); i++)
        {
            if (tt[i] == '0')
            {
                flagg = 1;
                countzero++;
            }
            else if (flagg == 1)
            {
                flag = 3;
                break;
            }
        }
        if (flag == 3 && countzero > cnt[0])
            flag = 1;
    }
    for (int i = 1; i < 10; i++)
    {
        if (cnt[i] > 0)
        {
            ll = i;
            break;
        }
    }
    string result;
    if (firstt != 0 && ll != 0)
    {
        if (ll < firstt)
        {
            result += (char)(ll+'0');
            cnt[ll]--;
            for (int i = 0; i < firstt; i++)
            {
                while (cnt[i] > 0)
                {
                    result += (char)(i+'0');
                    cnt[i]--;
                }
                ll = i+1;
            }
        }
        else if (ll == firstt && cnt[0] > 0 && (mintt != 0 || flag != 1))
        {
            result += (char)(ll+'0');
            cnt[ll]--;
            while (cnt[0] > 0)
            {
                result += '0';
                cnt[0]--;
            }
        }
        if (ll == firstt && flag != 1 && flag != 3)
        {
            while (cnt[ll] > 0)
            {
                result += (char)(ll+'0');
                cnt[ll]--;
            }
            ll = ll+1;
        }
    }
    else if (ll != 0)
    {
        result += (char)(ll+'0');
        cnt[ll]--;
        while (cnt[0] > 0)
        {
            result += '0';
            cnt[0]--;
        }
    }
    result += tt;
    for (int i = 0; i < 10; i++)
    {
        while (cnt[i] > 0)
        {
            result += (char)(i+'0');
            cnt[i]--;
        }
    }
    cout << result << endl;
    return 0;
}
    方法二:
    把整个数列分成3部分子数列前pre,子数列,子序列后
    首先
    将字符串best弄成子数列+子序列后的字符串
    接着

    设置子序列前的首字母为除0最小数字
    循环i从0~9 :
    在子序列前添加为i的全部数字
    判断best是否大于该序列+子序列+子序列后
    是就修改
    结束循环
    输出

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <numeric>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <vector>
#include <math.h>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>

using namespace std;

typedef long long ll;
typedef long double ld;

template <typename T>
T nextInt()
{
    T x = 0, p = 1;
    char ch;
    do
    {
        ch = getchar();
    }
    while(ch <= ' ');
    if (ch == '-')
    {
        p = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return x * p;
}

const int maxN = (int)1e6 + 10;
const int maxL = 17;
const int INF = (int)1e9;
const int mod = (int)1e9 + 7;
const ll LLINF = (ll)1e18;

vector <int> a(10);
vector <int> b(10);
char s[maxN];
char t[maxN];

string get(const vector<int>&cnt)
{
    string ret = "";
    for (int i = 0; i < 10; ++i)
    {
        ret += string(cnt[i], char('0' + i));
    }
    return ret;
}

int main()
{

    //  freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    gets(s);
    gets(t);

    if (strcmp(s, "01") == 0 || strcmp(s, "10") == 0)
    {
        puts("0");
        return 0;
    }

    int n = strlen(s);
    int m = strlen(t);

    for (int i = 0; i < n; ++i)
    {
        a[s[i] - '0']++;
    }
    for (int i =0 ; i < m; ++i)
    {
        b[t[i] - '0']++;
    }

    string T = (const char *) t;

    for (int len = 1; ; ++len)
    {
        vector <int> cnt = a;
        int tmp = len;
        int c = 0;
        while(tmp > 0)
        {
            cnt[tmp % 10]--;
            tmp /= 10;
            c++;
        }
        bool ok = true;
        for (int i = 0; i < 10; ++i)
        {
            cnt[i] -= b[i];
            if (cnt[i] < 0) ok = false;
        }
        if (ok && (t[0] != '0' || *max_element(cnt.begin() + 1, cnt.end())) > 0 && n - c == len)
        {

        }
        else continue;
        bool have = false;
        string best = "";
        {
            string cur = T + get(cnt);
            if (cur[0] != '0')
            {
                if (!have || best > cur)
                {
                    best = cur;
                    have = true;
                }
            }
        }
        string cur = "";
        for (int i = 1; i < 10; ++i)
        {
            if (cnt[i] > 0)
            {
                cur += char(i + '0');
                cnt[i]--;
                break;
            }
        }
        for (int i = 0; i <= 10; ++i)
        {
            string now = cur + T + get(cnt);

            if (now[0] != '0')
            {
                if (!have || best > now)
                {
                    best = now;
                    have = true;
                }
            }
            if (i != 10)
            {
                cur += string(cnt[i], char(i + '0'));
                cnt[i] = 0;
            }
        }
        assert(have);
        //   cout << len << '\n';
        puts(best.c_str());
        exit(0);
    }

    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值