https://blog.csdn.net/zuzhiang/article/details/79076522
传送门:Permute Digits
题目大意:
给你两个数 a和 b,可以打乱 a每位数的顺序,让你求满足 <=b 的最大值。保证结果一定存在。
思路:
由于结果一定存在,只有 b 的位数大于或等于 a 两种情况,如果 b 的位数大于 a 时,将 a 的每位数按从小到大的顺序输出即可。 当两者位数相等时,我们要尽可能保证结果的高位和 b的相应位相等,一旦出现结果的某一位小于 b,则将没用到的数按从小到大输出即可。
但是这样会出现一个问题,例如: a=1234 b=1230,当确认好前 3位为 123时,第 4位是不满足条件的,这时候要在回溯的过程中解决。
一点思考:
DFS其实就是用递归的方法按照一定顺序枚举所有可能的结果,所谓的回溯就是当当前路径不满足条件时,走别的路径看看是否满足条件,当满足条件时则退出,终止所有的递归。由于是按贪心的思维枚举的,所以比一般的暴力枚举的时间复杂度要低很多。
其实枚举一个小于的位就可以了。。。从低位向高位枚举。。。默认枚举的位i之前的位a和b都相同,第i位a小于b,后面取最大就行了,O(18^3)
#include<bits/stdc++.h>
#define rep(i, j, k) for (int i=j; i<k; i++)
#define ll long long
#define dprintf if (debug) printf
using namespace std;
int val(char s){
return s - '0';
}
char x[100],y[100], ans[100];
const int debug = 1;
int vis[100];
int lenx, leny;
int flag;
int main(){
scanf("%s", x);
scanf("%s", y);
lenx = strlen(x);
leny = strlen(y);
//dprintf("x = %s\n", x);
sort(x, x+lenx);
if (lenx < leny){
for (int i=lenx-1; i>=0; i--){
printf("%c", x[i]);
}
return 0;
}
for (int i=lenx; i>=0; i--){///?????????????keyijia1??
//di wei xiao
memset(vis, 0, sizeof(vis));
flag = true;
for (int j=0; j<i; j++){
int find = 0;
for (int k=0; k<lenx; k++){
if (x[k] == y[j] && !vis[k]){
vis[k] = 1;
ans[j] = x[k];
find = 1;
break;
}
}
if (!find) {
flag = false;
break;
}
}
if (!flag) continue;
if (i < lenx){
flag = false;
for (int j=lenx-1; j>=0; j--){
if (x[j]<y[i] && !vis[j]){
vis[j] = 1;
flag = true;
ans[i] = x[j];
break;
}
}
if (!flag) continue;
}
for (int j=i+1; j<lenx; j++){
for (int k=lenx-1; k>=0; k--){
if (!vis[k]){
vis[k] = 1;
ans[j] = x[k];
break;
}
}
}
//dprintf("i = %d\n", i);
printf("%s", ans);
return 0;
}
return 0;
}