一、实验目的
1、深入理解回溯法的深度优先搜索策略。
2、掌握用回溯法解题的算法框架。
3、学习并理解回溯法的设计策略。
二、问题描述
设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得,设wij是从供应商j处购得的部件i的重量,cij是相应的价格。试设计一个算法,计算总价格不超过c的最小重量机器设计。
算法设计:对于给定的机器部件重量和机器部件价格,计算总价格不超过d的最小重量机器设计。
- 输入
由文件input.txt给出输入数据,第1行输入3个正整数n,m和d。接下来的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
- 输出
将计算的最小重量及每个部件的供应商输出到文件output.txt。
上例输出为
4
1 3 1
- 数据结构
物理存储结构:顺序存储结构
数据的基本操作:插入,遍历查找
void mw(int i, int n, int m, int c[], int w[], int d, int cc, int cw, int cs[], int *bs);//计算最小重量
六、算法设计
#include <iostream>
using namespace std;
void mw(int i, int n, int m, int c[], int w[], int d, int cc, int cw, int cs[], int *bs);
int bw;
FILE *test,*answer;
int main()
{
for(int k=0; k<11; k++)
{
int n, m, d;
string testadd = "./test/machine" + to_string(k) + ".in", answeradd = "./answer/machine" + to_string(k) + ".out";
test = fopen(&testadd[0], "r"), answer = fopen(&answeradd[0], "r");
fscanf(test, "%d%d%d", &n, &m, &d);
int c[n*m], w[n*m], cs[n*m]= {0}, bs[n]= {0};
bw=10000;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
fscanf(test,"%d", &c[i*m+j]);
cs[i*m+j]=0;
}
}
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
fscanf(test,"%d", &w[i*m+j]);
}
}
mw(0, n, m, c, w, d, 0, 0, cs, bs);
int a,an[n];
int result=1;
fscanf(answer,"%d",&a);
printf("%d\n", bw);
for(int k = 0; k < n; k++)
{
printf("%d ", bs[k]);
fscanf(answer,"%d",&an[k]);
if(bs[k]!=an[k])
{
result=0;
}
}
printf("\n");
if(result==1)
cout<<"true"<<endl;
else
cout<<"false"<<endl;
}
return 0;
}
void mw(int i, int n, int m, int c[], int w[], int d, int cc, int cw, int cs[], int *bs)
{
if(i == n)
{
if(cw < bw)
{
bw = cw;
for(int k = 0; k < n; k++)
{
for(int p = 0; p < m; p++)
{
if(cs[k*m+p] == 1)
bs[k] = p+1;
}
}
}
return;
}
else
{
for(int j = 0; j < m ; j++)
{
if(cc + c[i*m+j] <= d)
{
if(cw+w[i*m+j]<bw)
{
cc += c[i*m+j];
cw += w[i*m+j];
cs[i*m+j] = 1;
mw(i + 1, n, m, c, w, d, cc, cw, cs, bs);
cc -= c[i*m+j];
cw -= w[i*m+j];
cs[i*m+j] = 0;
}
}
}
}
}
七、实验结果
八、实验心得
通过这次实验我理解了回溯法实际上是一个决策树的遍历过程,是个多叉树的遍历过程,它的基本思想是按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。当问题规模不是很大时,可以采用回溯的方法,递归遍历所有情况,能够找出全局最优解。