算法第五章作业
1.问题描述
设某一机器由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
2.代码
#include <bits/stdc++.h> using namespace std; int n,m,d; int w[40][40];//从供应商j 处购得的部件i的重量 int c[40][40];//cij是相应的价格 int x[40],X[40];// int minw=100000; int weight; int dsum=0;//总价格 void backtrack(int t){ if(t>n){//到达叶子节点 if(weight<minw){//更新最优值 minw=weight; for(int i=1;i<=n;i++){ X[i]=x[i];//同时记录选择的厂商 } } return; } else{ for(int i=1;i<=m;i++){ if(dsum+c[t][i]<=d&&weight+w[t][i]<minw){//之前已选的总价格加上接下来要选的机器价格,之前已选的机器总重量加上接下来要选的机器重量,同时满足条件 x[t]=i;//此处t表示行,每一行用来表示第1~n个部件;i表示列,表示第t个部件选择的是第i个厂家
weight+=w[t][i]; dsum+=c[t][i]; backtrack(t+1); weight-=w[t][i]; dsum-=c[t][i]; } } } } 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<<minw<<endl; for(int i=1;i<=n;i++){ cout<<X[i]<<" "; } }
3.解空间
123分别对应ABC三个厂家
(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)
4.解空间树
5.每个节点的状态值
每个节点的状态值有weight表示已选部件总重量(该重量有包含当前节点部件的重量)和dsum表示已选部件总价格(也包含当前节点部件的价格)
6.对回溯法的理解
回溯法的基本思想是构建问题的解空间树,在其解空间树中,从根节点出发,进行深度优先搜索。在搜索过程中,对解空间树的每个结点进行判断,判断该结点是否包含问题的解,若肯定不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯。否则,则进入该子树,继续按深度优先策略搜索。
在使用回溯法时,要注意用剪枝函数和限界函数避免不必要的尝试,从而提高算法的效率