算法第五章作业
算法第五章作业-最小重量机器设计问题
问题描述:
设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设wij是从供应商j 处购得的部件i的重量,cij是相应的价格。 试设计一个算法,给出总价格不超过d的最小重量机器设计。
输入格式:
第一行有3 个正整数n ,m和d, 0<n<30, 0<m<30, 接下来的2n 行,每行n个数。前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
参考代码:
#include<bits/stdc++.h> using namespace std; int wij[100][100]; int cij[100][100]; int x[100]; int bestx[1000]; int n,m,d; int minw=10000; int cw=0; int nowc=0; void backtrack(int t){ if(t>n){ minw=cw; for(int i=1;i<=n;i++){ bestx[i]=x[i]; } } else{ for(int i=1;i<=m;i++){ if(nowc+cij[t][i]<=d&&cw+wij[t][i]<minw){ x[t]=i; nowc+=cij[t][i]; cw+=wij[t][i]; backtrack(t+1); nowc-=cij[t][i]; cw-=wij[t][i]; } } } } int main(){ cin>>n>>m>>d; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>cij[i][j]; } } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>wij[i][j]; } } backtrack(1); cout<<minw<<endl; for(int i=1;i<=n;i++){ cout<<bestx[i]<<" "; } return 0; }
回溯法的方法分析“最小重量机器设计问题”:
三个数组 : wij[][] 存重量 、 cij[][]存价格 、 bestx[]存最优解
minw :最小重量 、 cw 当前重量 、 nowc 当前价格
void backtrack(int t){ if(t>n){//到达叶子节点 minw=cw; for(int i=1;i<=n;i++){ bestx[i]=x[i]; } } else{ for(int i=1;i<=m;i++){ if(nowc+cij[t][i]<=d&&cw+wij[t][i]<minw){//判断是否小于容量以及最低价格 x[t]=i;//符合=放入x[t]
//加入该点重量和价值 nowc+=cij[t][i]; cw+=wij[t][i]; backtrack(t+1);//到下一层
//回溯到上一层 nowc-=cij[t][i]; cw-=wij[t][i]; } } }
“最小重量机器设计问题"的解空间:
机器有三个部件,且三个部都有三个不同的供应商(1、2、3),通过排列组合,有以下解
{(1,1,1),(1,1,2),(1,1,3),(1,2,1),(1,2,2),(1,2,3),(1,3,1),(1,3,2),(1,3,3),(2,1,1),(2,1,2),(2,1,3),(2,2,1),(2,2,2),(2,2,3),(2,3,1),(2,3,2),(2,3,3),(3,1,1),(3,1,2),(3,1,3),(3,2,1),(3,2,2),(3,2,3),(3,3,1),(3,3,2),(3,3,3)}。
说明 “最小重量机器设计问题"的解空间树:

在遍历解空间树的过程中,每个结点的状态值是什么:
每个节点状态值是对应的重量和价格
如果满足约束条件,按以下进行分析与操作
for(int i=1;i<=m;i++){ if(nowc+cij[t][i]<=d&&cw+wij[t][i]<minw){//判断是否小于容量以及最低价格 x[t]=i;//符合=放入x[t] //加入该点重量和价值 nowc+=cij[t][i]; cw+=wij[t][i]; backtrack(t+1);//到下一层 //回溯到上一层 nowc-=cij[t][i]; cw-=wij[t][i]; } }
回溯算法的理解:
回溯算法解决问题的例子:n皇后问题,0-1背包问题,货郎问题。
回溯算法是一种选优搜索法,按选优条件向前搜索,以达到目标。简单的说是在搜索过程中寻找问题的解,当发现已不满足求解条件时,就回溯返回,尝试别的路径。
当探索到某一步时,发现原先选择不是目前的最优解或不满足问题条件时,就退回一步重新选择,并减去当前步骤的节点对应的值,这种方法为回溯法。
(2)剪枝函数:
一般回溯法会走剪枝函数,因为你回溯了,已经走了这个步骤,走过处理的逻辑,当前节点的数据存在参与计算。你退回上一步,则需要减去当前步骤的数据是吧。编写去除这些节点数据的函数就是剪枝函数。
2.回溯法解题步骤
(1)针对所给问题,确定问题的解空间: 首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解。
(2)确定结点的扩展搜索规则
(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。
这些问题的共同点是它们的解或者解集都是向量或者向量集,它们的搜索空间:树。可能是n叉树、子集树、排列树等。树的节点对应于部分向量,可行解在叶节点。 搜索方法有:DFS、BFS,或者二者结合。
回溯算法适用于求解搜索问题和优化问题,它采用DFS/BFS隐含的遍历搜索树。

浙公网安备 33010602011771号