📅  最后修改于: 2023-12-03 15:42:21.039000             🧑  作者: Mango
门|门 CS 1999 是一道经典的程序设计题目,要求设计一个程序,实现两门课程之间的选课问题。具体来说,有 n 门课程,每门课程都有 m 个选课学生,其中任意两个学生都选了不同的课程。现在需要选出 p 对课程并且满足两个条件:1)每个选课学生都选了恰好一对课程;2)从所有可行的选课方案中选择 p 对课程,要求这 p 对课程的交集为空集,即这些课程之间不存在公共选课学生。设计一个程序,输出满足条件的选课方案。
程序的输入格式如下:
第一行包含三个整数 n,m,p,表示课程数、每门课程选课学生数、要求的选课方案对数。
接下来 n 行,每行包含 m 个整数,用空格分隔,表示每门课程的选课学生编号。
程序的输出格式如下:
输出 p 行,每行包括两个整数,表示一对选课方案,用空格分隔。
3 4 2
1 2 3 4
4 3 2 1
1 3 2 4
1 3
2 3
这道题目要求我们输出所有符合要求的选课方案,需要用到深度优先搜索(DFS)算法。DFS 是一种常见的搜索算法,用于在一些非叶节点的分支下,沿着深度方向搜索更多的节点。对于本题,在搜索过程中,我们需要用一个 visited 数组来记录每个学生是否已被分配到某对选课方案中,以防止重复选取。
具体操作如下:
#include<bits/stdc++.h>
using namespace std;
vector<pair<int, int>> res; // 存放结果
vector<bool> visited(15, false); // 记录每个学生是否已被选
vector<vector<int>> arr; // 存储每门课程的选课学生编号
void dfs(int n, int m, int p, int cnt, int s, int e) {
if (cnt == p) { // 达到目标
for (auto r : res) { // 输出结果
cout << r.first << " " << r.second << "\n";
}
return;
}
if (s == n) return; //边界
if (e >= m) { // 下一门课
dfs(n, m, p, cnt, s + 1, s + 2);
return;
}
for (int i = s; i < n; ++i) {
for (int j = e; j < m; ++j) {
if (visited[arr[i][j]]) continue; // 已被选
bool flag = true; // 是否重叠
for (auto r : res) {
if ((r.first == i + 1 && r.second == (j / 2) + 1) || (r.second == i + 1 && r.first == (j / 2) + 1))
flag = false;
}
if (!flag) continue;
visited[arr[i][j]] = true; // 标记为已选
res.push_back(make_pair(i + 1, (j / 2) + 1)); // 加入结果
dfs(n, m, p, cnt + 1, s, j + 2);
res.pop_back(); // 回溯
visited[arr[i][j]] = false; // 标记为未选
}
}
}
int main() {
int n, m, p;
cin >> n >> m >> p;
arr.resize(n, vector<int>(m));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
cin >> arr[i][j];
dfs(n, m, p, 0, 0, 1);
return 0;
}