题目大意:给你两串数字a和b
让你重新排列第一串数字使得a比b小并且a要取到最大值
保证没有前导零
思路:一开始想着循环但是不会...
最终搜了一下答案写了dfs
思路就是一个数字一个数字的进行排列
如果排列的同一个位数数字正好对应b[i]的数字那么就继续排
如果同一个位数找不到比b[i]相等的时候就找比它小的数字排列了
并把剩下的数字进行从大到小进行排列(排列小的时候就已经比b小了,再怎么排都不会比b大)
最后输出答案即可
在这里要强调一下不能按字符串长度进行循环并dfs(会超时)
应该把每个数的个数数量存进去进行循环与dfs
最后记得剪枝回溯就好啦
具体看代码
AC代码:

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
string a,b;
int v[19]= {0};
char ans[20];
bool cmp(char a,char b)
{
    return a>b;
}
int len1;
int ok=1;
void dfs(int x)
{
    if(x==len1&&ok)
    {
        for(int i=0; i<len1; i++)cout<<ans[i];
        ok=0;
        return;
    }
    else if(!ok)return;
    for(int i=9; i>=0; i--)
    {
        if(v[i])//看这个数有没有被用过
        {
            if(i+'0'==b[x])//如果等于最好,继续递归
            {
                v[i]--;
                ans[x]=i+'0';
                dfs(x+1);
                v[i]++;
            }
            else if(i+'0'<b[x])//如果小于说明已经没方法,是最优解了直接输出
            {
                v[i]--;
                ans[x]=i+'0';
                for(int k=9; k>=0; k--)
                {
                    while(v[k])
                    {
                        ans[++x]=k+'0';
                        v[k]--;
                    }
                }
                if(ok)
                cout<<ans<<endl;
                ok=0;
                return;
            }
        }
    }
    return;
}
int main()
{
    cin>>a>>b;
    len1=a.size();
    int len2=b.size();
    if(len1<len2)
    {
        sort(a.begin(),a.end(),cmp);
        cout<<a;
    }
    else
    {
        for(int i=0;i<len1;i++){
            v[a[i]-'0']++;
        }
        dfs(0);
    }
    return 0;
}
/*
19875
19843
864791075345678672
234567890869429234
102
1000
2000000000001
2000000000000

*/