更新一下今天 “計算理論與算法設計” 期末考試的三道編程題,沒有測試用例的題真是太藍受了。分享一下我考試時的思路,最後也給出了我編寫的自測用例。僅供參考,如有錯誤還請指出~
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
輸出:37 3
1 2
1 4
2 4
輸出:510 9
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
輸出:53 1
1 2
輸出:25 3
1 2
3 4
4 1
輸出:37 7
3 6
7 1
1 6
1 2
2 3
2 6
6 4
輸出:48 10
7 8
1 6
3 5
4 5
6 7
3 1
1 4
2 7
1 2
3 6
輸出:4
end
歡迎關注個人公衆號“ 雞翅編程 ”,這裏是認真且乖巧的碼農一枚。
---- 做最乖巧的博客er,做最紮實的程序員 ----
旨在用心寫好每一篇文章,平常會把筆記彙總成推送更新~