题目大意:给你两串数字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
*/

京公网安备 11010502036488号