算法第五章上机作业
算法第五章作业
问题描述:
设某一机器由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 m,n,d;
int c[100][100];
int w[100][100];
int count1=0;//价格
int weight=0;//重量
int minn =1000000;
int x[100];
int minx[100];
void backtrack(int t){
if(t>n){
if(weight < minn && count1 <= d) {
minn = weight;
for(int i = 1;i <= n;i++){
minx[i] = x[i];
}
}
return;
}
else{
for(int i = 1;i <= m;i++){
if(c[t][i]+count1 <=d&&weight+ w[t][i] < minn){
x[t] = i;//i是供应商标记
count1 += c[t][i];
weight += w[t][i];
backtrack(t+1);
count1 -= c[t][i];
weight -= w[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<<minn<<endl;
for(int i = 1;i <= n;i++){
cout<<minx[i]<<" ";
}
return 0;
}
1.1 说明“最小重量机器设计问题"的解空间
解空间即进行穷举的搜索空间,包含所有的可能解,这里以样例为例写出解空间:
(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)
1.2 说明 “最小重量机器设计问题"的解空间树
1.3 在遍历解空间树的过程中,每个结点的状态值是什么
每个结点的状态值包括:该结点的重量weight、该结点的价格count。
2. 你对回溯算法的理解
回溯算法解决问题的例子:n皇后问题,0-1背包问题,货郎问题。
这些问题的共同点是它们的解或者解集都是向量或者向量集,它们的搜索空间:树。可能是n叉树、子集树、排列树等。树的节点对应于部分向量,可行解在叶节点。 搜索方法有:DFS、BFS,或者二者结合。
回溯算法适用于求解搜索问题和优化问题,它采用DFS/BFS隐含的遍历搜索树。
回溯算法的使用条件:多米诺性质,即:X1...Xn+1成立→X1...Xn成立,逆否命题也成立。