第5章-回溯法-习题
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
} }
//从1开始回溯 //构成1次全排列
//从结点t到叶结点 //将结点j作为当前结点
//将结点还回去
12
运动员最佳匹配问题算法
void pref::Compute(void) {
//计算当前排列的竞赛优势
for (int i=1,temp=0;i<=n;i++) //按题目要求计算
temp += p[i][r[i]]*q[r[i]][i];
最长处理时间作业优先, 机器空闲时间最长优先安排
18
最佳调度问题算法
void search(int dep) {
//初值为1
if (dep==n) {
//形成一种调度方案
int temp = comp();
//计算完成任务的时间
if (tmp<best) best = tmp; //更新最优解
return;
if (temp>best) {
//是更好的值?
best = temp;
for (int i=1; i<=n; i++) //构造最优解
bestr[i] = r[i];
}
}
13
运动员最佳匹配问题算法
14
运动员最佳匹配问题算法
main()中的前半部分:
15
5-17 最佳调度问题
假设有n 个任务由k 个可并行工作的机器完成。完成 任务i 需要的时间为ti。试设计一个算法找出完成这n 个任务的最佳调度,使得完成全部任务的时间最早。 编程任务: 对任意给定的整数n 和k,以及完成任务i 需要的时间 为ti,i=1~n 。编程计算完成这n个任务的最佳调度。
6
子集和问题算法
类似于装载问题 bool Subsum::backtrack(int i) {
if (i>n) { for (int j=1; j<=n; j++) bestx[j] = x[j]; bestw = cw; if (bestw==c) return true; else return false;
3
10 2 3
p 234
345
222
q
353
451
输出示例: 52
10
运动员最佳匹配问题
结果输出: 男女双方竞赛优势的总和的最大值。
样例分析
输出示例: 52
输入示例:
3
10 2 3 p 234
345
222
q
353
451
1 23
r1 3 2
10*2+4*5+4*3=52
for (int i=1,temp=0;i<=n;i++) temp += p[i][r[i]]*q[r[i]][i];
int tmp = 0;
//在k台机器中查找最大值
for (int i=0; i<k; i++)
if (len[i]>tmp) tmp = len[i];
return tmp;
}
20
5-30 离散01串问题
(n,k)01 串定义为:长度为n 的01 串,其中不含k 个连 续的相同子串。对于给定的正整数n 和k,计算(n,k)01 串的个数。
课程安排
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 周二 P P T T P T T P T T P T T T T P
周四 P
P
P
P
P
P
P
P
P
P
P
P
P
P
端午
考试 T
1
第5章 回溯法习题课
第5章 回溯法习题
1. 子集和问题 2. 运动员最佳匹配问题 3. 最佳调度问题 4. 离散01串问题
9
运动员最佳匹配问题
编程任务:
设计一个算法,对于给定的男女运动员竞赛优势,计算男女运 动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。
数据输入:
第一行有1 个正整数n (1≤n≤20)。接下来的2n 行,每行n 个数。 前n 行是p,后n 行是q。
结果输出: 男女双方竞赛优势的总和的最大值。输入示例:
}
for (int i=0; i<k; i++) {
//对每台机器回溯
len[i] += t[dep];
//安排任务dep(左子树)
if (len[i]<best) search(dep+1);
len[i] -= t[dep];
//右子树
}
}
19
最佳调度问题算法
计算完成任务的ቤተ መጻሕፍቲ ባይዱ间
int comp() {
给定2 个n×n 矩阵P 和Q。P[i][j] 是男运动员i 和 女运动员j 配对组成混合双打的男运动员竞赛优势; Q[i][j] 是女运动员i 和男运动员j 配合的女运动员竞 赛优势。 由于技术配合和心理状态等各种因素影响,P[i][j] 不一定等于Q[j][i] 。 男运动员i 和女运动员j 配对组成混合双打的男女双 方竞赛优势为P[i][j]*Q[j][i] 。 设计一个算法,计算男女运动员最佳配对法,使各 组男女双方竞赛优势的总和达到最大。
}
//从1开始调用 //计算完毕
//记录最优解
//满足条件(找到了)
7
子集和问题算法
r -= w[i];
//剩余大小
if (cw+w[i]<=c) {
//第i个数可以使用
x[i] = 1;
//左子树
cw += w[i];
//当前和加上w[i]
if (backtrack(i+1)) return true;
编程任务:
对于给定的正整数n 和k,计算(n,k)01 串的个数。
数据输入:
第一行有2 个正整数n 和k,1≤k,n≤40。
结果输出:
(n,k)01 串的个数。
输入示例
23
33→ 6
输出示例 4
4 3 → 10
5 3 → 16
21
5-30 离散01串问题
具有对称性,只要考察首字符为0的情况,将找到的符 合条件的0-1串的个数加倍。
void backtrack(int lev) {
//lev从2开始
if (lev>n) {
//一种情况构造完毕
tot += 2;
//个数加倍
return ;
}
for (int i=0; i<2; i++) {
bstr[lev] = i;
//满足条件就回溯
// 0,1
if ( bstrok(lev) ) backtrack(lev+1);
16
最佳调度问题
数据输入: 第一行有2 个正整数n 和k。第2 行的n 个正整数是完 成n 个任务需要的时间。 结果输出: 完成全部任务的最早时间。 输入示例 73 2 14 4 16 6 5 3 输出示例 17
17
4.7 多机调度问题
按算法greedy产生的作业调度如下图所示,所 需的加工时间为17。
cw -= w[i];
//准备进入右子树
}
if (cw+r>bestw) {//上界函数
x[i] = 0;
//右子树
if (backtrack(i+1)) return true;
}
r += w[i];
//右子树无最优解
return false;
}
8
5-4 运动员最佳匹配问题
问题描述: 羽毛球队有男女运动员各n 人。
程计算S 的一个子集S1,使得
xc
xs1
5
子集和问题
数据输入: 第1行有2个正整数n和c,n表示S的大小,c是子集 和的目标值。接下来的1 行中,有n个正整数,表示 集合S 中的元素。 结果输出: 输出子集和问题的解。当问题无解时,输出“No solution! ”。 输入示例 5 10 22654 输出示例 226
}
//第lev位
//lev的前k位坐标x[0]~x[k-1] //下标必须大于0 //是相同的
//每隔i个位置
23
5-30 离散01串问题
//判断是否相同
bool same() {
int len = x[0] - x[1];
//计算位置差
for (int i=0; i<len; i++)
//搜索每一位
只有一个下标是变化的
11
运动员最佳匹配问题算法
解空间是一棵排列树 void pref::Backtrack(int t) {
if (t>n) Compute(); else
for (int j=t; j<=n; j++) { swap(r[t], r[j]); Backtrack(t+1); swap(r[t], r[j]);
for (int j=1; j<k; j++)
//每次搜索k位
if (bstr[x[j]+i]!=bstr[x[j-1]+i]) //相邻位
return false;
//只要有一个不相同即可
return true;
//相同
}
24
5-30 离散01串问题
文件头: #include <iostream> using namespace std;
int n, k; int tot; short *bstr; int *x;
bool bstrok(int lev); bool same();
25
4
5-1 子集和问题
子集和问题的一个实例为〈S,t〉。其中,S={ x1,x2,…,xn}
是一个正整数的集合,c是一个正整数。
子集和问题判定是否存在S 的一个子集S1,使得 x c
xs1
试设计一个解子集和问题的回溯法。
编程任务:
对于给定的正整数的集合S={ x1,x2,…,xn}和正整数c,编
}
}
22
5-30 离散01串问题
bool bstrok(int lev) { for (int i=0; i<k; i++) x[i] = lev-i; while (x[k-1]>0) { if (same()) return false; for (int i=0; i<k; i++) x[i] -= i+1; } return true;
//从1开始回溯 //构成1次全排列
//从结点t到叶结点 //将结点j作为当前结点
//将结点还回去
12
运动员最佳匹配问题算法
void pref::Compute(void) {
//计算当前排列的竞赛优势
for (int i=1,temp=0;i<=n;i++) //按题目要求计算
temp += p[i][r[i]]*q[r[i]][i];
最长处理时间作业优先, 机器空闲时间最长优先安排
18
最佳调度问题算法
void search(int dep) {
//初值为1
if (dep==n) {
//形成一种调度方案
int temp = comp();
//计算完成任务的时间
if (tmp<best) best = tmp; //更新最优解
return;
if (temp>best) {
//是更好的值?
best = temp;
for (int i=1; i<=n; i++) //构造最优解
bestr[i] = r[i];
}
}
13
运动员最佳匹配问题算法
14
运动员最佳匹配问题算法
main()中的前半部分:
15
5-17 最佳调度问题
假设有n 个任务由k 个可并行工作的机器完成。完成 任务i 需要的时间为ti。试设计一个算法找出完成这n 个任务的最佳调度,使得完成全部任务的时间最早。 编程任务: 对任意给定的整数n 和k,以及完成任务i 需要的时间 为ti,i=1~n 。编程计算完成这n个任务的最佳调度。
6
子集和问题算法
类似于装载问题 bool Subsum::backtrack(int i) {
if (i>n) { for (int j=1; j<=n; j++) bestx[j] = x[j]; bestw = cw; if (bestw==c) return true; else return false;
3
10 2 3
p 234
345
222
q
353
451
输出示例: 52
10
运动员最佳匹配问题
结果输出: 男女双方竞赛优势的总和的最大值。
样例分析
输出示例: 52
输入示例:
3
10 2 3 p 234
345
222
q
353
451
1 23
r1 3 2
10*2+4*5+4*3=52
for (int i=1,temp=0;i<=n;i++) temp += p[i][r[i]]*q[r[i]][i];
int tmp = 0;
//在k台机器中查找最大值
for (int i=0; i<k; i++)
if (len[i]>tmp) tmp = len[i];
return tmp;
}
20
5-30 离散01串问题
(n,k)01 串定义为:长度为n 的01 串,其中不含k 个连 续的相同子串。对于给定的正整数n 和k,计算(n,k)01 串的个数。
课程安排
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 周二 P P T T P T T P T T P T T T T P
周四 P
P
P
P
P
P
P
P
P
P
P
P
P
P
端午
考试 T
1
第5章 回溯法习题课
第5章 回溯法习题
1. 子集和问题 2. 运动员最佳匹配问题 3. 最佳调度问题 4. 离散01串问题
9
运动员最佳匹配问题
编程任务:
设计一个算法,对于给定的男女运动员竞赛优势,计算男女运 动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。
数据输入:
第一行有1 个正整数n (1≤n≤20)。接下来的2n 行,每行n 个数。 前n 行是p,后n 行是q。
结果输出: 男女双方竞赛优势的总和的最大值。输入示例:
}
for (int i=0; i<k; i++) {
//对每台机器回溯
len[i] += t[dep];
//安排任务dep(左子树)
if (len[i]<best) search(dep+1);
len[i] -= t[dep];
//右子树
}
}
19
最佳调度问题算法
计算完成任务的ቤተ መጻሕፍቲ ባይዱ间
int comp() {
给定2 个n×n 矩阵P 和Q。P[i][j] 是男运动员i 和 女运动员j 配对组成混合双打的男运动员竞赛优势; Q[i][j] 是女运动员i 和男运动员j 配合的女运动员竞 赛优势。 由于技术配合和心理状态等各种因素影响,P[i][j] 不一定等于Q[j][i] 。 男运动员i 和女运动员j 配对组成混合双打的男女双 方竞赛优势为P[i][j]*Q[j][i] 。 设计一个算法,计算男女运动员最佳配对法,使各 组男女双方竞赛优势的总和达到最大。
}
//从1开始调用 //计算完毕
//记录最优解
//满足条件(找到了)
7
子集和问题算法
r -= w[i];
//剩余大小
if (cw+w[i]<=c) {
//第i个数可以使用
x[i] = 1;
//左子树
cw += w[i];
//当前和加上w[i]
if (backtrack(i+1)) return true;
编程任务:
对于给定的正整数n 和k,计算(n,k)01 串的个数。
数据输入:
第一行有2 个正整数n 和k,1≤k,n≤40。
结果输出:
(n,k)01 串的个数。
输入示例
23
33→ 6
输出示例 4
4 3 → 10
5 3 → 16
21
5-30 离散01串问题
具有对称性,只要考察首字符为0的情况,将找到的符 合条件的0-1串的个数加倍。
void backtrack(int lev) {
//lev从2开始
if (lev>n) {
//一种情况构造完毕
tot += 2;
//个数加倍
return ;
}
for (int i=0; i<2; i++) {
bstr[lev] = i;
//满足条件就回溯
// 0,1
if ( bstrok(lev) ) backtrack(lev+1);
16
最佳调度问题
数据输入: 第一行有2 个正整数n 和k。第2 行的n 个正整数是完 成n 个任务需要的时间。 结果输出: 完成全部任务的最早时间。 输入示例 73 2 14 4 16 6 5 3 输出示例 17
17
4.7 多机调度问题
按算法greedy产生的作业调度如下图所示,所 需的加工时间为17。
cw -= w[i];
//准备进入右子树
}
if (cw+r>bestw) {//上界函数
x[i] = 0;
//右子树
if (backtrack(i+1)) return true;
}
r += w[i];
//右子树无最优解
return false;
}
8
5-4 运动员最佳匹配问题
问题描述: 羽毛球队有男女运动员各n 人。
程计算S 的一个子集S1,使得
xc
xs1
5
子集和问题
数据输入: 第1行有2个正整数n和c,n表示S的大小,c是子集 和的目标值。接下来的1 行中,有n个正整数,表示 集合S 中的元素。 结果输出: 输出子集和问题的解。当问题无解时,输出“No solution! ”。 输入示例 5 10 22654 输出示例 226
}
//第lev位
//lev的前k位坐标x[0]~x[k-1] //下标必须大于0 //是相同的
//每隔i个位置
23
5-30 离散01串问题
//判断是否相同
bool same() {
int len = x[0] - x[1];
//计算位置差
for (int i=0; i<len; i++)
//搜索每一位
只有一个下标是变化的
11
运动员最佳匹配问题算法
解空间是一棵排列树 void pref::Backtrack(int t) {
if (t>n) Compute(); else
for (int j=t; j<=n; j++) { swap(r[t], r[j]); Backtrack(t+1); swap(r[t], r[j]);
for (int j=1; j<k; j++)
//每次搜索k位
if (bstr[x[j]+i]!=bstr[x[j-1]+i]) //相邻位
return false;
//只要有一个不相同即可
return true;
//相同
}
24
5-30 离散01串问题
文件头: #include <iostream> using namespace std;
int n, k; int tot; short *bstr; int *x;
bool bstrok(int lev); bool same();
25
4
5-1 子集和问题
子集和问题的一个实例为〈S,t〉。其中,S={ x1,x2,…,xn}
是一个正整数的集合,c是一个正整数。
子集和问题判定是否存在S 的一个子集S1,使得 x c
xs1
试设计一个解子集和问题的回溯法。
编程任务:
对于给定的正整数的集合S={ x1,x2,…,xn}和正整数c,编
}
}
22
5-30 离散01串问题
bool bstrok(int lev) { for (int i=0; i<k; i++) x[i] = lev-i; while (x[k-1]>0) { if (same()) return false; for (int i=0; i<k; i++) x[i] -= i+1; } return true;