更新一下今天 “计算理论与算法设计” 期末考试的三道编程题,没有测试用例的题真是太蓝受了。分享一下我考试时的思路,最后也给出了我编写的自测用例。仅供参考,如有错误还请指出~
03
成绩 15 开启时间 2020年06月24日 星期三 15:10 折扣 0.8 折扣时间 2020年06月24日 星期三 18:30 允许迟交 否 关闭时间 2020年06月24日 星期三 18:30 题目描述:
农场主决定把奶牛带到位置较远新的草场,为了提高效率,他有如下考虑:1)带尽可能多的牛过去;2)有些牛在一起赶路时可能相互打架影响速度,这样的牛不能一起走,所以每组这样的奶牛,最多只能带一头。你的任务是帮农场主确定最多带多少奶牛去新草场。
输入格式:
第1行有2个正整数n(0<n<20)和m(0<m<160),分别表示奶牛的数目和不能一起走的奶牛组的数目。奶牛编号为1,2,…,n。
接下来的m行中,每行有2个正整数i和j,表示i与j不能一起走(i<j)。
输出格式:
输出一行,要带走牛的最大数目。
测试输入 期待的输出 时间限制 内存限制 额外进程 测试用例 1
- 7 10↵
- 1 2↵
- 1 4↵
- 2 4↵
- 2 3↵
- 2 5↵
- 2 6↵
- 3 5↵
- 3 6↵
- 4 5↵
- 5 6↵
- 3↵
1秒 64M 0
此题可以考虑用回溯,枚举所有不会冲突的情况,找到最大值(其实就是一个最大团问题的模型)。由于考试时间比较紧,我没有剪枝。代码很好理解,直接上完整代码和测试用例:
//
// Created by A on 2020/6/24.
//
#include <cstdio>
#include <algorithm>
#define MAXN 25
using namespace std;
int n, m;
bool match[MAXN][MAXN]; //false即不匹配
bool choose[MAXN] = {false}; //记录是否选择了此牛
int cur = 0, ans = 0;
/* 处理输入 */
void Init() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
match[i][j] = true;
int p, q;
for (int i = 1; i <= m; i++) {
scanf("%d %d", &p, &q);
match[p][q] = match[q][p] = false;
}
}
/* 判断第 x 头牛是否可以加入 */
bool IsValid(int x) {
for(int i = 1; i < x; i++)
if(choose[i] && !match[i][x]) //如果选择了第 i 头牛且不与本头牛匹配
return false;
return true;
}
void backtrack(int step) {
bool flag = false;
/* 回溯的终点 */
if (step > n) {
ans = max(cur, ans);
return;
}
//如果可以加入,就考虑加入
if(IsValid(step)) {
flag = true;
cur++;
choose[step] = true;
backtrack(step + 1);
}
//如果之前加入过,之后要考虑不加入的情况,需要恢复数据
if(flag) {
choose[step] = false;
cur--;
}
//考虑不加入
backtrack(step + 1);
}
int main() {
Init();
backtrack(1);
printf("%d\n", ans);
}
测试用例:
7 10
1 2
1 4
2 4
2 3
2 5
2 6
3 5
3 6
4 5
5 6
输出:3
7 3
1 2
1 4
2 4
输出:5
10 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
输出:5
3 1
1 2
输出:2
5 3
1 2
3 4
4 1
输出:3
7 7
3 6
7 1
1 6
1 2
2 3
2 6
6 4
输出:4
8 10
7 8
1 6
3 5
4 5
6 7
3 1
1 4
2 7
1 2
3 6
输出:4
end
欢迎关注个人公众号“ 鸡翅编程 ”,这里是认真且乖巧的码农一枚。
---- 做最乖巧的博客er,做最扎实的程序员 ----
旨在用心写好每一篇文章,平常会把笔记汇总成推送更新~