概述
目录
1. 请用回溯法的方法分析“最小重量机器设计问题”
最小重量机器设计问题描述
问题描述:
输入格式:
输出格式:
输入样例:
输出样例:
回溯法的基本步骤:
常用剪枝函数:
1.1 说明“最小重量机器设计问题”的解空间
1.2 说明 “最小重量机器设计问题"的解空间树
1.3 在遍历解空间树的过程中,每个结点的状态值是什么
1.4 代码
2. 你对回溯算法的理解
1. 请用回溯法的方法分析“最小重量机器设计问题”
最小重量机器设计问题描述
问题描述:
设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设wij是从供应商j 处购得的部件i的重量,cij是相应的价格。
试设计一个算法,给出总价格不超过d的最小重量机器设计。
输入格式:
第一行有3 个正整数n ,m和d, 0<n<30, 0<m<30, 接下来的2n 行,每行m个数。前n行是c,后n行是w。
输出格式:
输出计算出的最小重量,以及每个部件的供应商。
输入样例:
3 3 4
1 2 3
3 2 1
2 2 2
1 2 3
3 2 1
2 2 2
输出样例:
4
1 3 1
回溯法的基本步骤:
(1)针对所给问题,定义问题的解空间;
(2)确定易于搜索的解空间结构;
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索
常用剪枝函数:
用约束函数在扩展结点处剪去不满足约束的子树;
用限界函数剪去得不到最优解的子树。
1.1 说明“最小重量机器设计问题”的解空间
理解问题:一共购置n个部件,每个部件可以从m个供应商手中获得,故每个部件有m中选择。
所有可能结果:
{1, 1, ……,1}、{2, 1, ……,1}、{3, 1, ……, 1}
……
{m,m,……,m}
每个大括号里一共n个数字,对应n个部件,取值从1到m对应m个供应商,每个部件都分别有m种可能的选择,一共有m^n种可能的结果。
1.2 说明 “最小重量机器设计问题"的解空间树
不剪枝看,这棵解空间树是一棵m叉树,一共n层,第几层结点的状态值就对应第几个部件的选择,是哪个供应商;添加剪枝函数,使得该树被剪枝,删去不满足价格小于d以及得不到最优解的可能,最终使得整体在满足价格不超过d的条件下购置n个商品的最小重量。
剪枝函数:
约束函数contains():满足当前已购置商品的价格不超过d
限界函数bound():判断当前已购置商品的重量不会超过已获得的最优解(价格不超过d条件下的最小重量),如果超过了,则不用再往下遍历该结点了,肯定得不到最优解,回溯看上一步选择其他值是否可能得到最优解。
1.3 在遍历解空间树的过程中,每个结点的状态值是什么
假设该结点是第i层的结点,同时该结点的值为j,表示状态为第i个部件选择在第j个供应商处购置。
1.4 代码
#include <iostream>
using namespace std;
int n; // n个部件
int m; // m个供应商
int w[30][30];
// w[i][j]:从供应商j处购得部件i的重量
int c[30][30];
// c[i][j]:从供应商j处购得部件i的价格
// 1 <= i <= n ; 1 <= j <= m
int x[30], bestx[30];
// 1到n个部件分别选择的供应商
int leastw = 0x3f3f3f3f;
// 预算d条件下购置n个部件的最小重量
int cw;
// 当前重量
int cost;
// 当前价格
int d;
// 总价格不超过d
bool contains(int t) { // 限界
return (cost + c[t][x[t]] <= d);
}
bool bound(int t) {
return (cw + w[t][x[t]] < leastw);
}
void backtrack(int t) { // 依次判断1到n个部件
if(t > n) {
if(cw < leastw) {
leastw = cw;
for(int i = 1; i <= n; i++)
bestx[i] = x[i];
}
return;
}
for(int i = 1; i <= m; i++) { // 依次观察m个供应商
x[t] = i;
if(contains(t) && bound(t)) {// 剪枝:价格小于d条件下,重量尽可能小
cost += c[t][x[t]];
cw += w[t][x[t]];
backtrack(t+1);
cost -= c[t][x[t]];
cw -= w[t][x[t]];
}
}
}
int main() {
cin >> n >> m >> d;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin >> c[i][j];
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin >> w[i][j];
}
}
backtrack(1);
cout << leastw << endl;
for(int i = 1; i <= n; i++) {
cout << bestx[i] << " ";
}
}
2. 你对回溯算法的理解
目前我所学过的解空间树分为子集树、排列树和n叉树(最小重量机器设计问题),思想都大致相同,像是“试错”,把每种可能的结果走一遍,不行(用剪枝函数)或到叶子结点就回溯,继续看另一种结果是否可以获得想要的结果。
我目前写代码的步骤,首先是把所有可能的结果都想到,构建解空间;之后是将所有可能的结果在一棵解空间树上体现出来;最后是用深度搜索的方法遍历解空间树,同时根据需要采用剪枝函数,删去不可行结果和减少遍历时间,当遍历完,答案也就出来了。
最后
以上就是悲凉溪流为你收集整理的算法设计与分析第五章作业1. 请用回溯法的方法分析“最小重量机器设计问题”2. 你对回溯算法的理解的全部内容,希望文章能够帮你解决算法设计与分析第五章作业1. 请用回溯法的方法分析“最小重量机器设计问题”2. 你对回溯算法的理解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复