1 solutions

  • 0
    @ 2025-4-8 12:03:27

    标准的深度优先搜索+回溯 问题建模

    将问题转化为经典的“排列问题”,即从每本书中选择一个未被分配且被当前人喜欢的书,逐步构建完整的分配方案。

    DFS递归框架

    递归层级:每个层级对应一个人(例如第1层处理第1个人)。

    选择范围:遍历所有书,跳过已被分配的或不被当前人喜欢的。

    状态标记:用vis数组记录哪些书已被分配,避免重复使用。

    回溯恢复:每次递归返回后,需要撤销当前选择,尝试其他可能性。

    字典序保证

    由于遍历书的顺序总是从1到m,且每次优先选择较小的书号,最终方案会自然按字典序生成,无需额外排序。

    #include <bits/stdc++.h>
    using namespace std;
    
    int a[15][15];      // 存储喜好矩阵(a[i][j]=1表示第i个人喜欢第j本书)
    int n, m;            // 人数n,书数m
    vector<int> tem;     // 临时存储当前分配方案
    vector<vector<int>> ans; // 存储所有合法方案
    int vis[70];         // 标记书是否被分配(vis[j]=1表示书j已被分配)
    
    void dfs(int x) {    // x表示当前处理到第几个人
        if (x == n + 1) { // 递归终止条件:所有人处理完毕
            ans.push_back(tem);
            return;
        }
        for (int i = 1; i <= m; i++) { // 遍历所有书
            if (vis[i] || a[x][i] == 0) continue; // 跳过已被分配或不喜欢的书
            vis[i] = 1;       // 标记书i为已分配
            tem.push_back(i); // 当前人选书i
            dfs(x + 1);       // 递归处理下一个人
            vis[i] = 0;       // 回溯:撤销分配
            tem.pop_back();    // 回溯:移除当前选择
        }
    }
    
    int main() {
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                cin >> a[i][j];
        dfs(1); // 从第1个人开始递归
        // 输出所有方案(已按字典序排列)
        for (auto &vec : ans) {
            for (int j : vec) cout << j << " ";
            cout << endl;
        }
    }
    
    • 1

    Information

    ID
    1452
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    7
    Tags
    # Submissions
    120
    Accepted
    27
    Uploaded By