Permute Digits
CodeForces - 915CYou 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.
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.
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.
123 222
213
3921 10000
9321
4940 5000
4940
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;
}