题意:一个数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;
}