1 条题解

  • 0
    @ 2025-5-13 11:34:35

    一、问题核心

    本题围绕大规模邮寄信件的邮编处理规则展开,核心是对输入的 5 位邮政编码数据集进行分析与处理,根据美国邮政服务的批量邮寄规则,将信件按邮编分类捆绑。需准确统计 5 位邮编捆绑、3 位邮编捆绑以及按一类邮件(平信)邮寄的信件数量,同时识别并记录无效邮编,最终按特定格式输出处理结果。

    二、关键思路

    (一)数据存储与初始化 使用数组 zip_cnt[100000] 记录每个 5 位邮政编码出现的次数,初始化为 0 。这样在读取输入数据时,可通过对应邮编值作为数组下标,方便统计其出现频率。 定义结构体 Bundle 包含 letter_cnt(信件数量)和 bun_cnt(捆绑数量),用数组 buns[100000] 存储邮编捆绑信息,用于后续记录 5 位和 3 位邮编捆绑的相关数据,初始化为 0 。 利用二维数组 invalid_record[100000][10] 存储无效邮政编码,invalid_cnt 记录无效邮编数量,初始化为 0 。 total_letters 记录总信件数,total_buns 记录总捆绑数,初始化为 0 。 (二)邮编有效性检查 编写函数 validity_check(char buffer[]) 对输入邮编进行有效性判断: 位数检查:通过 strlen(buffer) 函数获取邮编字符串长度,判断是否恰好为 5 位,若不满足则直接返回 false 。 数字检查:遍历邮编字符串的每个字符,判断是否在 '0' 到 '9' 范围内,若存在非数字字符则返回 false 。 全 0 检查:设置标志位 flag ,遍历邮编字符,若发现有非 0 字符则将 flag 设为 false 并跳出循环,若遍历完仍为 true ,说明邮编全为 0 ,返回 false 。只有同时满足以上三个条件,才返回 true ,认定邮编有效。 (三)5 位邮编捆绑处理 编写函数 process1(void) 处理 5 位邮编捆绑。 遍历所有可能的 5 位邮编(范围是 10000 到 99999),对于 zip_cnt[i] >= 10 的邮编进行捆绑: 优先尝试每次捆绑 15 封信,通过循环不断将 buns[i].letter_cnt 增加 15 ,buns[i].bun_cnt 、total_letters 、total_buns 相应增加,同时 zip_cnt[i] 减去 15 ,直到 zip_cnt[i] < 15 。 若剩余信件数 zip_cnt[i] >= 10 ,则将剩余信件全部捆绑,更新相关计数,将 zip_cnt[i] 置为 0 。 按序输出 5 位邮编捆绑信息,包括邮编、信件数量和捆绑数量。 清空用于记录 3 位邮编捆绑信息的数组 buns 中对应 100 到 999 下标的元素,为后续处理 3 位邮编捆绑做准备。 (四)3 位邮编捆绑处理 编写函数 process2(void) 处理 3 位邮编捆绑。 遍历 100 到 999 的 3 位邮编,对于每个 3 位邮编 i : 先统计其下所有 5 位邮编(num = i * 100 + j ,其中 j 从 0 到 99)的信件总数,将相关信息存储到临时数组 temp 中,并将 zip_cnt[num] 置为 0 。 按照与 5 位邮编捆绑类似的方式,优先捆绑 15 封信,再处理剩余信件(若剩余信件数大于等于 10 则再捆绑一次) 。对于剩余信件,根据临时数组 temp 中记录的每个 5 位邮编的信件数,将剩余信件合理分配回对应的 zip_cnt 数组中。 若 buns[i].letter_cnt > 0 ,按 dddxx 格式输出 3 位邮编捆绑信息,包括邮编、信件数量和捆绑数量。 (五)一类邮件处理 编写函数 process3(void) 处理按一类邮件邮寄的信件。 遍历 10000 到 99999 的 5 位邮编,对于 zip_cnt[i] > 0 的邮编,说明该邮编的信件数量不足 10 封,按一类邮件邮寄,输出邮编、信件数量(即 zip_cnt[i] )和捆绑数量 0 ,并将信件数量累加到 total_letters 中。 (六)无效邮编输出 编写函数 output_invalid(void) 输出无效邮编。 遍历 invalid_record 数组,通过字符串比较函数 strcmp 去除重复的无效邮编,然后输出所有不重复的无效邮编。 (七)主函数逻辑 在 main 函数中: 初始化 invalid_cnt 为 0 。 循环读取输入的邮编,调用 validity_check 函数判断有效性: 若有效,将邮编转换为数字并对 zip_cnt 数组对应下标元素加 1 。 若无效,将邮编复制到 invalid_record 数组中,并增加 invalid_cnt 。 依次调用 process1 、process2 、process3 函数进行 5 位邮编捆绑处理、3 位邮编捆绑处理和一类邮件处理。 输出总信件数 total_letters 和总捆绑数 total_buns 。 调用 output_invalid 函数输出无效邮编。

    代码实现

    #include <cstdio>
    #include <string>
    #include <cstring> // 添加 <cstring> 头文件
    #include <algorithm>
    using namespace std;
    
    struct Bundle {
        int letter_cnt, bun_cnt;
    };
    
    Bundle buns[100000];
    char buffer[10], invalid_record[100000][10];
    int invalid_cnt, zip_cnt[100000], total_letters, total_buns;
    
    bool M[100000];
    
    bool validity_check(char buffer[]) {
    
        // 位数检查
        if (strlen(buffer) != 5) {
            return false;
        }
    
        // 数字检查
        for (int i = 0; i < 5; i++) {
            if (buffer[i] < '0' || buffer[i] > '9') {
                return false;
            }
        }
    
        // 全0检查
        bool flag = true;
        for (int i = 0; i < 5; ++i) {
            if (buffer[i] != '0') {
                flag = false;
                break;
            }
        }
        if (flag) {
            return false;
        }
        return true;
    }
    
    void process1(void) {
    
        // 同5位10份以上打包
        for (int i = 10000; i <= 99999; ++i) {
            if (zip_cnt[i] >= 10) {
                while (zip_cnt[i] >= 15) {
                    buns[i].letter_cnt += 15;
                    ++buns[i].bun_cnt;
                    total_letters += 15;
                    ++total_buns;
                    zip_cnt[i] -= 15;
                }
                if (zip_cnt[i] >= 10) {
                    buns[i].letter_cnt += zip_cnt[i];
                    ++buns[i].bun_cnt;
                    total_letters += zip_cnt[i];
                    ++total_buns;
                    zip_cnt[i] = 0;
                }
            }
        }
    
        // 按序输出
        printf("ZIP         LETTERS     BUNDLES\n");
        puts("");
        for (int i = 10000; i <= 99999; ++i) {
            if (buns[i].letter_cnt != 0) {
                printf("%d%12d%12d\n", i, buns[i].letter_cnt, buns[i].bun_cnt);
            }
        }
        puts("");
    
        // 清空三位数的桶
        for (int i = 100; i <= 999; ++i) {
            buns[i].letter_cnt = buns[i].bun_cnt = 0;
        }
    }
    
    void process2(void) {
    
        // 同3位10份以上打包
        for (int i = 100; i <= 999; ++i) {
            int temp[100][2];
            int cnt = 0, letter_cnt = 0;
            for (int j = 0; j <= 99; ++j) {
                int num = i * 100 + j;
                if (zip_cnt[num] > 0) {
                    temp[cnt][0] = num;
                    temp[cnt][1] = zip_cnt[num];
                    letter_cnt += zip_cnt[num];
                    zip_cnt[num] = 0;
                    ++cnt;
                }
            }
            while (letter_cnt >= 15) {
                ++buns[i].bun_cnt;
                ++total_buns;
                buns[i].letter_cnt += 15;
                total_letters += 15;
                letter_cnt -= 15;
            }
            if (letter_cnt >= 10) {
                ++buns[i].bun_cnt;
                ++total_buns;
                buns[i].letter_cnt += letter_cnt;
                total_letters += letter_cnt;
                letter_cnt = 0;
            }
            while (letter_cnt > 0) {
                if (temp[cnt - 1][1] >= letter_cnt) {
                    zip_cnt[temp[cnt - 1][0]] += letter_cnt;
                    break;
                } else {
                    zip_cnt[temp[cnt - 1][0]] += temp[cnt - 1][1];
                    letter_cnt -= temp[cnt - 1][1];
                    --cnt;
                }
            }
            if (buns[i].letter_cnt > 0) {
                printf("%dxx%12d%12d\n", i, buns[i].letter_cnt, buns[i].bun_cnt);
            }
        }
        puts("");
    }
    
    void process3(void) {
        // first class 输出
        for (int i = 10000; i <= 99999; ++i) {
            if (zip_cnt[i] > 0) {
                printf("%d%12d%12d\n", i, zip_cnt[i], 0);
                total_letters += zip_cnt[i];
            }
        }
        puts("");
    }
    
    void output_invalid(void) {
        // 非法zip-code输出
        printf("INVALID ZIP CODES\n\n");
        for (int i = 0; i < invalid_cnt; ++i) {
            bool flag = true;
            for (int j = 0; j < i; ++j) {
                if (strcmp(invalid_record[i], invalid_record[j]) == 0) {
                    flag = false;
                }
            }
            if (flag) {
                printf("%s\n", invalid_record[i]);
            }
        }
    
    }
    int main(void) {
        invalid_cnt = 0;
        while (scanf("%s", buffer) != EOF) {
            if (validity_check(buffer)) {
    
                // 桶排序
                int num = 0;
                for (int i = 0; i < 5; ++i) {
                    num = num * 10 + buffer[i] - '0';
                }
                ++zip_cnt[num];
            } else {
                strcpy(invalid_record[invalid_cnt], buffer);
                ++invalid_cnt;
            }
        }
    
        process1();
        process2();
        process3();
        printf("TOTALS%11d%12d\n\n", total_letters, total_buns);
        output_invalid();
    
        return 0;
    }
    
    
    • 1

    信息

    ID
    56
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者