看上去不难,但一直在WA…
开始的算法是:从左往右构造结果res[i],在a没被选择的数字中,选择<=b[i]的最大值,如果选择的值<
b[i],之后每一步都选择剩余数字中最大的。
问题在于:有可能选择了某个数字,导致之后不可能再构造出<=b的结果
123456789123456789
276193619183618162
Output
276193619�88755443
Answer
276193618987554432
两种办法:直接的是,如果构造到某个位置i,没有<=b[i]的值,则像退栈一样,直到退到某一位,可以选择比这一位当前选择的值更小的。选择这个更小的值,继续进行构造。
题解的做法:从左往右构造结果,选择的数字为:选择了这个数字后,之后一定可以构造出<=b的结果;每一步选择符合此条件的最大数字。判断之后能否有<=b的结果:把剩余数字从小到大放在后面,得到的数字<=b则能够构造出。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[20], b[20];
bool used[20];
int sa, sb, ans[20];
// max char <= ch
int choose(char ch) {
int mx = -1;
for (int i = 0; i < sa; i++) {
if (!used[i] && a[i] <= ch && (mx == -1 || a[i] > a[mx])) {
mx = i;
}
}
return mx;
}
// judge if b[i] > a[ans[j]]
bool lower(int j) {
for (int i = 0; i < j; i++) {
if (a[ans[i]] < b[i]) {
return true;
}
}
return false;
}
int main() {
scanf("%s %s", a, b);
memset(used, false, sizeof(used));
sa = strlen(a);
sb = strlen(b);
// strlen(b) >= strlen(a)
if (sb > sa) {
int j = 0;
for (int i = 0; i < sa; i++) {
int mx = choose('9');
ans[j++] = mx;
used[mx] = true;
}
} else {
int j = 0;
for (int i = 0; i < sb; i++) {
int mx = choose(lower(j) ? '9' : b[i]);
if (mx == -1) {
j--;
// cannot choose smaller
while (choose(a[ans[j]] - 1) == -1) {
used[ans[j--]] = false;
}
used[ans[j]] = false;
ans[j] = choose(a[ans[j]] - 1);
used[ans[j]] = true;
i = j++;
} else {
ans[j++] = mx;
used[mx] = true;
}
}
}
for (int i = 0; i < sa; i++) {
printf("%c", a[ans[i]]);
}
printf("\n");
return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[20], b[20], res[20];
int counts[15];
bool smaller(char* res) {
if (strlen(b) > strlen(res)) return true;
for (int i = 0; i < strlen(res); i++) {
if (res[i] > b[i]) return false;
else if (res[i] < b[i]) return true;
}
return true;
}
bool check(int i, int j) {
res[i++] = j + '0';
for (int k = 0; k <= 9; k++) {
int t = counts[k];
if (k == j) t--;
while (t--) {
res[i++] = k + '0';
}
}
res[i] = '\0';
return smaller(res);
}
int main() {
scanf("%s %s", a, b);
memset(counts, 0, sizeof(counts));
for (int i = 0; i < strlen(a); i++) {
counts[a[i] - '0']++;
}
for (int i = 0; i < strlen(a); i++) {
int j;
for (j = 9; j >= 0; j--) {
if (counts[j] == 0) continue;
if (check(i, j)) break;
}
res[i] = j + '0';
counts[j]--;
}
for (int i = 0; i < strlen(a); i++) {
printf("%c", res[i]);
}
printf("\n");
return 0;
}