1. 请用回溯法的方法分析“最小重量机器设计问题”
1.1 说明“最小重量机器设计问题"的解空间
解空间是以数量为n的产品和数量为m的供应商所形成的解集
1.2 说明 “最小重量机器设计问题"的解空间树
以每个产品为一个layer,每个layer的节点都会有m个分支。该分支表示当前layer表示的产品所选择的供应商。叶子节点则对应该方案下完成该机器设计的重量
1.3 在遍历解空间树的过程中,每个结点的状态值是什么
每个结点的状态值表示的是当前的重量值。
附上求解最小机器设计问题的源代码:
#include<iostream>
using namespace std;
int n, m, d, best = 0x3f3f3f3f, c[30][30], w[30][30];
int ca[30], wa[30], ans[30], mv[30], mw[30];
bool check(int t) {
int tvalue = 0, tw = 0;
for(int i = 1; i <= t; i++) {
tvalue += c[i][ca[i]];
tw += wa[i];
}
for(int i = t+1; i <= n; i++) {
tvalue += mv[i];
tw += mw[i];
}
if(tvalue > d || tw > best)return false;
else return true;
}
void backtrack(int t) {
if(t > n) {
int temp = 0;
for(int i = 1; i <= n; i++) {
temp += wa[i];
}
if(temp < best) {
best = temp;
for(int i = 1; i <= n; i++){
ans[i] = ca[i];
}
}
return;
}
for(int i = 1; i <= m; i++) {
ca[t] = i;
wa[t] = w[t][i];
if(check(t)){
backtrack(t + 1);
}
}
}
int main() {
cin >> n >> m >> d;
for(int i = 1; i <= n; i++) {
int min = 0x3f3f3f3f;
for(int j = 1; j <= m; j++) {
cin >> c[i][j];
if (c[i][j] < min)min = c[i][j];
}
mv[i] = min;
}
for(int i = 1; i <= n; i++) {
int min = 0x3f3f3f3f;
for(int j = 1; j <= m; j++) {
cin >> w[i][j];
if (w[i][j] < min)min = w[i][j];
}
mw[i] = min;
}
backtrack(1);
cout << best << endl;
for(int i = 1; i <= n; i++) {
cout << ans[i] << " ";
}
}
2. 你对回溯算法的理解
所谓回溯算法,就是我们常说的DFS算法,本质上就是一种暴力穷举算法。在解决这么一个回溯问题,实际上就是一个决策树的遍历过程。但为了提高求解效率与减少程序的运行时间。往往会在回溯树的某个节点上进行剪枝操作。
用句通俗的话来说就是,从一条路往前走,能走就走下去,走不下去就退回来,换一条路来试试,重点在于进行状态的回退。