算法第五章作业

算法第五章作业-最小重量机器设计问题 

问题描述:

  设某一机器由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 wij[100][100];
int cij[100][100];
int x[100];
int bestx[1000];
int n,m,d;
int minw=10000;
int cw=0; 
int nowc=0;



void backtrack(int t){
    if(t>n){
        minw=cw;
        for(int i=1;i<=n;i++){
            bestx[i]=x[i];
        }
    }
    else{
        for(int i=1;i<=m;i++){
            if(nowc+cij[t][i]<=d&&cw+wij[t][i]<minw){
                x[t]=i;
                nowc+=cij[t][i];
                cw+=wij[t][i];
                backtrack(t+1);
                nowc-=cij[t][i];
                cw-=wij[t][i];
            }
        }        
    }
}
int main(){
    cin>>n>>m>>d;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>cij[i][j]; 
        }
}
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>wij[i][j]; 
        }
}
        backtrack(1);
        cout<<minw<<endl;
        for(int i=1;i<=n;i++){
            cout<<bestx[i]<<" ";
        }
        return 0;
}
 

回溯法的方法分析“最小重量机器设计问题”:

三个数组 : wij[][] 存重量 、 cij[][]存价格 、 bestx[]存最优解

minw :最小重量 、 cw 当前重量 、 nowc 当前价格

void backtrack(int t){
    if(t>n){//到达叶子节点
        minw=cw;
        for(int i=1;i<=n;i++){
            bestx[i]=x[i];
        }
    }
    else{
        for(int i=1;i<=m;i++){
            if(nowc+cij[t][i]<=d&&cw+wij[t][i]<minw){//判断是否小于容量以及最低价格
                x[t]=i;//符合=放入x[t]
         //加入该点重量和价值 nowc
+=cij[t][i]; cw+=wij[t][i]; backtrack(t+1);//到下一层
          //回溯到上一层 nowc
-=cij[t][i]; cw-=wij[t][i]; } } }

“最小重量机器设计问题"的解空间:

机器有三个部件,且三个部都有三个不同的供应商(1、2、3),通过排列组合,有以下解

{(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)}。

 

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

 

 

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

每个节点状态值是对应的重量和价格 

如果满足约束条件,按以下进行分析与操作

for(int i=1;i<=m;i++){
            if(nowc+cij[t][i]<=d&&cw+wij[t][i]<minw){//判断是否小于容量以及最低价格
                x[t]=i;//符合=放入x[t]
         //加入该点重量和价值
                nowc+=cij[t][i];
                cw+=wij[t][i];
                backtrack(t+1);//到下一层
          //回溯到上一层
                nowc-=cij[t][i];
                cw-=wij[t][i];
            }
        }  

 

回溯算法的理解:

回溯算法解决问题的例子:n皇后问题,0-1背包问题,货郎问题。

回溯算法是一种选优搜索法,按选优条件向前搜索,以达到目标。简单的说是在搜索过程中寻找问题的解,当发现已不满足求解条件时,就回溯返回,尝试别的路径。

当探索到某一步时,发现原先选择不是目前的最优解或不满足问题条件时,就退回一步重新选择,并减去当前步骤的节点对应的值,这种方法为回溯法。

(2)剪枝函数:

一般回溯法会走剪枝函数,因为你回溯了,已经走了这个步骤,走过处理的逻辑,当前节点的数据存在参与计算。你退回上一步,则需要减去当前步骤的数据是吧。编写去除这些节点数据的函数就是剪枝函数。
2.回溯法解题步骤
(1)针对所给问题,确定问题的解空间: 首先应明确定义问题的解空间,问题的解空间应至少包含问题的一个(最优)解。

(2)确定结点的扩展搜索规则

(3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

这些问题的共同点是它们的解或者解集都是向量或者向量集,它们的搜索空间:树。可能是n叉树、子集树、排列树等。树的节点对应于部分向量,可行解在叶节点。 搜索方法有:DFS、BFS,或者二者结合。

回溯算法适用于求解搜索问题和优化问题,它采用DFS/BFS隐含的遍历搜索树。

posted @ 2021-12-13 00:27  Fan文韬武略~  阅读(74)  评论(0)    收藏  举报