4307. 数字重构

给定两个正整数 aa 和 bb,均不含前导 00。

现在,请你对 aa 进行重构,重新排列其各位数字顺序,得到一个不含前导 00 的新正整数。

要求新正整数在不超过 bb 的前提下,尽可能大。

输出新正整数。

注意,我们允许新正整数等于 aa,即保持原样不变。

输入格式

第一行包含一个正整数 aa。

第二行包含一个正整数 bb。

两个输入数字均不含前导 00。

输出格式

一个不含前导 00 的正整数,表示答案。

数据保证一定有解。

数据范围

前 66 个测试点满足 1≤a,b≤1091≤a,b≤109。
所有测试点满足 1≤a,b≤10181≤a,b≤1018。

输入样例1:

123
222

输出样例1:

213

输入样例2:

3921
10000

输出样例2:

9321

输入样例3:

4940
5000

输出样例3:

4940

思路:额前几个样例搞懂了,后面几个不知道咋整了,看了别人的 

贪心版的

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
string a, b;
void cal(int i)
{
    if(i == a.size()) return;

    sort(a.begin() + i + 1, a.end(), greater());//把a未确定的所有位数(i后面的)递减排序

    if(a[i] >= b[i])
        for(int j = i; j < a.size(); j ++)
            if(a[j] <= b[i])
            {
                //=========== 
                string s = a;//临时串
                swap(s[i], s[j]);//后半部分是降序的,所以每次会贪心取到大的作为当前位
                sort(s.begin() + i + 1, s.end(), greater());//后半部分最大的情况
                if(s <= b){ //前半部分满足条件,后半部分最大,如果满足条件立刻返回
                    a = s;
                    return;
                }
                //===========

                sort(s.begin() + i + 1, s.end());//后半部分最小的情况
                if(s > b) continue;//后半部分最小也满足不了条件

                else//后半部分还有机会操作,那么这一步就用a[j]的数和当前位的数交换
                {
                    swap(a[i], a[j]);
                    cal(i + 1);
                    return;
                }
            }
}
int main()
{

    cin >> a >> b;
    sort(a.begin(), a.end(), greater());
    if(a.size() == b.size()) cal(0);

    cout << a << endl;
    return 0;
}

作者:小念
链接:https://www.acwing.com/solution/content/94319/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

bfs版

#include <bits/stdc++.h>
using namespace std;
long long A, B;
int a[20], b[20], cnt[20], ans[20], ta, tb;
bool dfs(int u, int f) {
    if (u > ta) return 1;
    for (int i = 9; i >= (u == 1 ? 1 : 0); i--) {
        if ((f && i > b[u]) || !cnt[i]) continue;
        cnt[i]--; ans[u] = i;
        if (dfs(u + 1, f && i == b[u])) return 1;
        cnt[i]++;
    }
    return 0;
}
int main() {
    cin >> A >> B;
    while (A) a[++ta] = int(A % 10), A /= 10;
    while (B) b[++tb] = int(B % 10), B /= 10;
    for (int i = 1; i <= ta; i++) cnt[a[i]]++;
    if (tb > ta) {
        sort(a + 1, a + 1 + ta, greater<int>());
        for (int i = 1; i <= ta; i++) cout << a[i];
        return 0;
    }
    reverse(a + 1, a + 1 + ta); reverse(b + 1, b + 1 + tb);
    dfs(1, 1);
    for (int i = 1; i <= ta; i++) cout << ans[i];
    return 0;
}

作者:封禁用户
链接:https://www.acwing.com/solution/content/94979/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值