UPC2022新生赛30场

问题 G: 数字替换

题目描述

味味很喜欢玩一个数字替换的游戏,数字替换游戏是这样的:给出一个 n 位正整数 a, 然后再给你一个长度为 m 的数字序列 b,味味可以用 b 中的一些数字与 a 中各个位置上的 数字进行一对一的交换(当然也可以选择不交换)。当然 b 中的每个位置上的数字最多只能 被使用一次。这个游戏的目的是经过一系列替换后,使 a 的数值达到最大。
味味很聪明,在位数不多的情况下,总能快速的求出最后 a 的最大数值,但是当 n 很 大时,味味就无能为力了,所以她希望会写程序的你帮助她快速的求解 a 最后能到达的那 个最大值。

输入

输入共包含三行。第一行两个用空格隔开的正整数 n,m。第二行一个正整数 a(a 的最高位必定不是 0)。第三行一个长度为 m 的数字序列 b。

输出

输出仅包含一行一个数值,表示 a 最大可能达到的数值(输出不能含前导0)。

样例输入 Copy

4 3
1024
010

样例输出 Copy

1124

提示

b 中的一个 1 和 a 中的第二位上的 0 进行交换。

对于 20%的数据 1≤n,m≤10 
对于 50%的数据 1≤n,m≤2000 
对于 100%的数据 1≤n,m≤100000

心得:

就分享一道题目吧,这道题目我也是由于不认真读题才导致多次更改,坐题之前一定要看好条件啊,这道题目首先给出了两个条件m, n代表着输入的两个字符串的长度,但是,由于粗心吧,我直接忘记使用这两个条件了, 直接当成整数输入肯定会错。

:第一遍错误代码(不想看的话可以直接蹦到最下面ac代码

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
bool cmp(int a, int b) {
    return a > b;
}
int main() {
    int n, m, i, j, k, num;
    char op[100100];
    int a[100100], b[100010];
    cin >> n >> m;
    scanf("%d\n", &num);
    for (i = 0; i < m; i++) {
        op[i] = getchar();
    }
    op[++i] = '\0';
    int len1 = strlen(op); //字符串的长度
    for (i = 0; op[i] != '\0'; i++) {
        b[i] = op[i] - '0';
    }
    sort (b, b + j, cmp);
    int len2 = 0; //数字的长度
    i = 0;
    while (num) {
        a[i++] = num % 10;
        num /= 10;
        //cout << num << endl;
        len2++;
    }
    //倒着循环比较;
    j = 0;
    for (i = len2 - 1; i >= 0; i--) {
        for (j = 0; j < len1; j++) {
            if (b[j] > a[i]) {
                a[i] = b[j];
                b[j] = -1;
                break;
            }
        }
    }
    //cout << len1 << endl;
    int sum = 0;
    for (i = len2 - 1; i >= 0; i--) {
        sum = sum * 10 + a[i];
    }
    printf("%d", sum);
    return 0;
}

写的麻烦又麻烦,算是给各位提个醒吧;

接下来说一下这道题目的正确做法:输入两个字符串(直接用scanf就可以)

对第二个字符串用sort进行排序, 从大到小;

大小比较,大的话就把第二个赋值给第一个!!!!问题是这里要求每一个只能用一次,也就是说我们要想办法跳过去这一步,我感觉这个题我唯一写的比较节省时间的地方就是这里:

k = 0;
    for (i = 0; i < m; i++) {
        for (j = k; j < n; j++) {
            if (bp[j] - '0' > op[i] - '0') {
                k++;
                op[i] = bp[j];
                break;
            } else {
                break;
            }
        }
    }

这里看似是两个循环,其实只有一个循环,里面的用k巧妙的避开了上一次使用过的数据,因为已经处理过了,而且只用比较一次,比较省事,也不会担心超时(我讨厌超时orz)

最后附上ac代码,本人能力有限,写这篇博客也是出于反思和总结,希望能帮到你们!

#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(char a, char b) {
    return a - '0' > b - '0';
}
char op[100010], bp[100010];

int main() {
    int m, n, i, j, k;
    cin >> m >> n;
    /*i = 0;
    while ((op[i] = getchar()) != '\n') {
        i++;
    }
    op[i] = '\0';
    i = 0;
    while ((bp[i] = getchar()) != '\n') {
        i++;
    }
    bp[i] = '\0';*/
    scanf("%s", op);
    scanf("%s", bp);
    sort(bp, bp + n, cmp);
    k = 0;
    for (i = 0; i < m; i++) {
        for (j = k; j < n; j++) {
            if (bp[j] - '0' > op[i] - '0') {
                k++;
                op[i] = bp[j];
                break;
            } else {
                break;
            }
        }
    }
    for (i = 0; i < m; i++) {
        printf("%c", op[i]);
    }
    return 0;
}