1 条题解

  • 0
    @ 2025-5-13 12:07:35

    一、问题核心

    ACM 市美食俱乐部 16 位成员需在 5 个晚上安排晚宴座位,4 张桌子每张坐 4 人,且任意两位成员在这 5 个晚上恰好同桌一次。已知前三晚座位安排,需判断能否补全后两晚安排,若能则输出完整 5 天安排,若不能则提示无法完成。

    二、算法标签

    回溯算法:用于尝试所有可能的座位安排组合,当不满足条件时回溯重新安排。 约束满足问题(CSP):成员之间的同桌约束条件,即任意两人在 5 个晚上恰好同桌一次,属于约束满足问题的范畴。 图论(二分图匹配相关思想):可将成员看作图的节点,同桌关系看作边,座位安排问题转化为图的边的合理分配问题,类似二分图匹配的思想(虽然不完全相同,但有类似的元素,即如何合理分配节点到不同的组中满足特定条件)。 组合数学:从 16 个成员中选择合适的成员组合安排到不同桌子上,涉及组合数学中组合的概念和计算。

    三、关键思路

    (一)数据结构设计 成员关系矩阵:创建一个 16×16 的矩阵,用于记录任意两个成员是否已经同桌过。矩阵元素 matrix[i][j] 表示成员 i 和成员 j 的同桌次数,初始化为 0,每次安排座位后更新。 座位安排数据结构:使用二维列表来表示每晚的座位安排,例如 night = [['A', 'B', 'C', 'D'], ['E', 'F', 'G', 'H'], ['I', 'J', 'K', 'L'], ['M', 'N', 'O', 'P']],其中每个子列表表示一张桌子的成员。 (二)回溯过程 尝试安排座位:从第四晚开始,尝试将成员分配到 4 张桌子上,每张桌子 4 人。在分配过程中,根据成员关系矩阵判断当前分配是否满足约束条件,即任意两人同桌次数为 1。 回溯操作:如果当前分配不满足条件(例如,存在两人同桌次数超过 1 或者未满足每张桌子 4 人等条件),则回溯到上一步,重新分配成员。 剪枝优化:在回溯过程中,若发现当前分配已经无法满足后续条件(例如,剩余成员无法合理分配到桌子上),则直接回溯,避免不必要的尝试,提高算法效率。 (三)输出处理 成功情况:若成功完成后两晚的座位安排,则将前五晚的座位安排按要求格式输出,即前三晚的输入加上后两晚的安排。 失败情况:若遍历完所有可能的安排都无法满足条件,则输出提示信息 “It is not possible to complete this schedule.”。

    代码实现

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    // 使用 long long 替代 std::int64_t
    long long min(long long a, long long b, long long c, long long d)
    {
        a = a > b? b : a;
        a = a > c? c : a;
        a = a > d? d : a;
        return a;
    }
    
    int main()
    {
        int a, b, c, d, n, i;
        long long f[6000]; // 使用 long long
        a = 0; b = 0; c = 0; d = 0;
        memset(f, 0, sizeof(f));
        f[0] = 1;
        
        for(i = 1; i < 5900; i++)
        {
            f[i] = min(f[a] * 2, f[b] * 3, f[c] * 5, f[d] * 7);
            if(f[i] == f[a] * 2) a++; // 修正逻辑错误:每次只增加一个指针
            if(f[i] == f[b] * 3) b++;
            if(f[i] == f[c] * 5) c++;
            if(f[i] == f[d] * 7) d++;
        }
        
        while(cin >> n && n)
        {
            cout << "The ";
            printf("%d", n);
            if(n % 10 == 1 && n % 100 != 11)
                cout << "st";
            else if(n % 10 == 2 && n % 100 != 12)
                cout << "nd";
            else if(n % 10 == 3 && n % 100 != 13)
                cout << "rd";
            else
                cout << "th";
            cout << " humble number is ";
            printf("%lld.\n", f[n-1]); // 使用%lld格式化输出 long long
        }
        return 0;
    }
    
    
    • 1

    信息

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