算法第五章上机实践报告

1. 请用回溯法的方法分析最小重量机器设计问题

问题描述

7-2 最小重量机器设计问题 (25 )

设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得。设wij是从供应商j 处购得的部件i的重量,cij是相应的价格。 试设计一个算法,给出总价格不超过d的最小重量机器设计。

输入格式:

第一行有3 个正整数n md 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 n, m, d, cw = 0, cc = 0, bestw = 999999;

int w[31][31];

int c[31][31];

int bests[31];

int s[31];

 

void backtrack(int t){

        if(t > n){

                if(cw < bestw){

                        bestw = cw;

                }

                for(int i = 1; i <= n; i++){

                        bests[i] = s[i];

                }

        }

        else{

                for(int i = 1; i <= m; i++){

                        cc += c[t][i];

                        cw += w[t][i];

                        s[t] = i;

                        if((cc <= d) && (cw < bestw)){

                                backtrack(t + 1);

                        }

                        cc -= c[t][i];

                        cw -= 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 << bestw << endl;

        for(int i = 1; i <= n; i++){

                cout << bests[i] << " ";

        }

       

        return 0;

}

1.1     说明最小重量机器设计问题"的解空间

解空间是所有可能解的集合,所以本题的解空间为{{131}{132}{133}}

1.2     说明最小重量机器设计问题"的解空间树

解空间树是一棵m叉树,m个分支代表选择哪个供应商

1.3 在遍历解空间树的过程中,每个结点的状态值是什么

        当前的总价格cv和总重量cw

2. 你对回溯算法的理解

  回溯算法就是个多叉树的遍历问题,关键就是在前序遍历和后序遍历的位置做一些操作,算法框架如下:

 def backtrack(...):

    for 选择 in 选择列表:

        做选择

        backtrack(...)

        撤销选择

  backtrack 函数时,需要维护走过的「路径」和当前可以做的「选择列表」,当触发「结束条件」时,将「路径」记入结果集。某种程度上说,动态规划的暴力求解阶段就是回溯算法。只是有的问题具有重叠子问题性质,可以用备忘录优化,将递归树大幅剪枝,这就变成了动态规划。

posted on 2021-12-14 19:07  PurLinE  阅读(39)  评论(0编辑  收藏  举报