題意:一個數a和一個數b,不含前導零,移動a的數字的位置,使得a成爲比b小的最大的數。
題解:用一個數組存a中的數,一個數組存b中的數。從大到小對a排序。如果a的數字個數比b少,直接輸出。
如果是一樣長,記錄a中數字出現的次數,然後dfs。因爲最大的數是1e18,直接dfs a中的數字會超時,所以就dfs 0到9這十個數
如果出現了比b中對應的數字小的數字,就直接把剩下的數字從大到小填進去,如果是一樣的,就搜索下一個,如果這種情況不行
就回溯。如果成功找到了所有數字,就返回。
#pragma warning(disable:4996)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int a[20], b[20], ans[20];
int vis[20];
int La, Lb, solved;
char s1[20], s2[20];
bool cmp(int x, int y)
{
return x > y;
}
void dfs(int x, int flag)//x代表當前是求第幾個數字
{
int i;
if (solved)return;
if (x == La)
{
solved = 1;
return;
}
for (i = 9; i >= 0; i--)
{
if (vis[i] > 0)//數字個數大於0
{
if (flag || i < b[x])//之前的或者是當前的數比b對應數字小
{
ans[x] = i;
vis[i]--;
dfs(x + 1, 1);
vis[i]++;//回溯
if (solved)return;
}
else if (i == b[x])
{
ans[x] = i;
vis[i]--;
dfs(x + 1, flag);
vis[i]++;
if (solved)return;
}
/*else if (i < b[x])
{
ans[x] = i;
vis[i]--;
dfs(x + 1, 1);
vis[i]++;
if (solved)return;
}*/
}
}
}
int main()
{
int i, j;
while (scanf("%s%s", s1, s2) == 2)
{
La = strlen(s1); Lb = strlen(s2);
memset(vis, 0, sizeof(vis));
for (i = 0; i < La; i++)
{
a[i] = s1[i] - '0';
vis[a[i]]++;
}
for (i = 0; i < Lb; i++)
b[i] = s2[i] - '0';
sort(a, a + La, cmp);//排序
if (La < Lb)//a的數字個數比b少
{
for (i = 0; i < La; i++)
printf("%d", a[i]);
cout << endl;
}
else if (La == Lb)
{
solved = 0;
dfs(0, 0);
for (i = 0; i < La; i++)
printf("%d", ans[i]);
cout << endl;
}
}
return 0;
}