Description
You 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.
Input
The first line contains integer a (1
≤
a
≤
10
18
). The second line contains integer b (1
≤
b
≤
10
18
). Numbers don’t have leading zeroes. It is guaranteed that answer exists.
Output
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.
Examples
Input | Output |
---|---|
123 222 | 213 |
Input | Output |
---|---|
3921 10000 | 9321 |
Input | Output |
---|---|
4940 5000 | 4940 |
题意:输入两个数
a
和
思路:找到不大于
b
的最大的数,根据数的性质,理想的数最好每一位都应该接近
解法:
- 动态规划解决,记录a中0~9出现的次数
- 从最高位(i=0)开始,并假设能找到和b一样的数
- 如果在a中有至少一个b[i],就把b[i]填到答案的第i位,并把a中b[i]的次数-1
- 如果在a中没有b[i],或者在此位填b[i]不合理,说明假设不成立,在a中继续找一个最接近b[i]-1的数填到答案中
- 如果能找到,说明之前的填法是正确而且最大的,那么把a中没用到的数按从大到小依次填到答案中,所得到的数就是最佳的答案
- 如果不能找到,说明之前的填法有问题,之前的有一位只能接近不能等于,那么返回到上一位
- 如果在此位填b[i]合理,继续下一位(i++)
- 如果b的位数比a多,则a无论怎么排列都一定小于b,直接把a按从大到小排列所得的最大数就是答案
#include <stdio.h>
#include <string.h>
int na, nb;
char a[20];
char b[20];
int cnta[10];
int numb[20];
char ans[20];
//int cntans[10];
#define c2n(ch) (ch-'0')
#define n2a(num) (num+'0')
bool solve(int t) {
if (t == na)return true;//填好了
//处理答案的第t位
if (cnta[numb[t]] > 0) {//如果a中还有b[t],就尝试填入
--cnta[numb[t]];
ans[t] = b[t];
//解释:solve(t+1)处理下一位,如果填好了就返回true,不能这样填就返回false
if (solve(t + 1) == false) {//当前位填b[i]不合适,必须填更小的数进去
++cnta[numb[t]];//把之前填入的numb[t]取出来
int lt = numb[t] - 1;//lt 取 less than之意
while (cnta[lt] <= 0 && lt >= 0)--lt;//寻找合适的比b[i]小的数
if (lt < 0)return false;//没有找到
else {
//找到了,把lt填到答案
--cnta[lt];
ans[t] = lt + '0';
//从这里开始已经有一个高位比b小了,只需要把剩下的位按最大把b填满就行
int gt = 9;
for (int asi = t+1; asi < na; ++asi) {
while (cnta[gt] <= 0 && gt >= 0)--gt;
ans[asi] = gt + '0';
--cnta[gt];
}
return true;//题意保证一定有答案
}
}
//如果填的数是合适的就不做任何操作
return true;
}
else {如果a中没有有b[t],就找一个小的数填入
int lt = numb[t];
while (cnta[lt] <= 0 && lt >= 0)--lt;
if (lt < 0)return false;//没有找到
else {
//找到了,把lt填到答案
--cnta[lt];
ans[t] = lt + '0';
//从这里开始已经有一个高位比b小了,只需要把剩下的位按最大把b填满就行
int gt = 9;
for (int asi = t+1; asi < na; ++asi) {
while (cnta[gt] <= 0 && gt >= 0)--gt;
ans[asi] = gt + '0';
--cnta[gt];
}
return true;
}
}
}
int main() {
for (na = 0;;na++) {
scanf("%c", &a[na]);
if (a[na] == '\n')break;
cnta[c2n(a[na])]++;
}
for (nb = 0;; nb++) {
scanf("%c", &b[nb]);
if (b[nb] == '\n')break;
numb[nb] = c2n(b[nb]);
}
if (nb > na) {
for (int t = 9;t>=0;--t) {
while (cnta[t]-- > 0) {
printf("%c", n2a(t));
}
}
}
else {
solve(0);
for (int i = 0; i < na; i++) {
printf("%c", ans[i]);
}
}
}
趁着刚ac把思路整理到博客,感觉有点杂乱,说是动态规划其实一点也不像,想清楚了再优化下吧。