Permute Digits CodeForces - 915C (DFS)

本文介绍CodeForces-915C题目解决方案,通过深度优先搜索算法解决给定两个正整数a和b的情况下,如何对a进行数位排列以构造不超过b的最大数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Permute Digits

CodeForces - 915C

You are given two positive integer numbers a and b. Permute (change order) of the digits of a to construct maximal number not exceeding b. No number in input and/or output can start with the digit 0.

It is allowed to leave a as it is.

Input

The first line contains integer a (1 ≤ a ≤ 1018). The second line contains integer b (1 ≤ b ≤ 1018). Numbers don't have leading zeroes. It is guaranteed that answer exists.

Output

Print the maximum possible number that is a permutation of digits of a and is not greater than b. The answer can't have any leading zeroes. It is guaranteed that the answer exists.

The number in the output should have exactly the same length as number a. It should be a permutation of digits of a.

Example
Input
123
222
Output
213
Input
3921
10000
Output
9321
Input
4940
5000
Output
4940
一开始直接用stl中的prev_permutation果断超时,后来看网上用深度搜索再剪枝可以降低复杂度

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char a[100],b[100],ans[100];
int lena,lenb;
int vis[11];
int solve;
void dfs(int dep,int flag){//dep代表位数,flag=1代表已经有当前位小于b的当前位了以后只需要从已知的数中从大到小放进答案数组就可以
    if(solve) return;//如果已经解决了,就直接返回
    if(dep == lena){//达到a的长度说明得到了答案了
        solve = 1;
        return ;
    }
    int i;
    for(i = 9; i >= 0; i--){//从大到小遍历数字
        if(vis[i]){//如果这个数字能用
            if(flag||b[dep]==i+'0'){//如果前面已经有一个位是小于b的对应位了,那么后面的只需要从大到小遍历的可行的数依次放入答案数组即可
                vis[i]--;           //如果相等,则先放入,如果这位放下这个相等的后不合适,下一步会回溯遍历一定没有符合条件的数会回溯回来继续找
                ans[dep] = i+'0';
                dfs(dep+1,flag);
                if(solve)return;//这句必须有
                vis[i]++;
            }
            else if(b[dep]>i+'0'){//如果目前最大的能用的数直接小于b的对应位,那么直接放入,标记flag为1,以后的每位直接把还能用的从大到小放进答案数组即可
                vis[i]--;
                ans[dep] = i+'0';
                dfs(dep+1,1);
                if(solve)return;//这句必须有
                vis[i]++;
            }
        }
    }
}
int main(){
    scanf("%s%s",a,b);
    lena = strlen(a);
    lenb = strlen(b);
    if(lena < lenb){//如果a的长度比b的短直接从大到小输出
        sort(a,a+lena);
        int i;
        for(i = lena-1; i >= 0; i--){
            printf("%c",a[i]);
        }
        return 0;
    }
    else{
        int i;
        memset(vis,0,sizeof(vis));
        for(i = 0; i < lena; i++){
            vis[a[i]-'0']++;//记录下每个数字出现的次数,dfs时直接倒着遍历选取可以用的数字
        }
        solve = 0;
        dfs(0,0);
        for(i = 0; i < lena; i++)
            printf("%c",ans[i]);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值