最小重量机器设计问题”问题描述

   设某一机器由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 <iostream>
using namespace std;

int n, m, d;
int c[30][30];
int w[30][30];
int nowweight;
int minweight = 1000000;
int cost;
int x[30];
int y[30]; 

// bool place(int t){ 
//     for(int i=1; i<t; i++){
//         if(cost + c[t][i] > d) //&& x[t] == x[i] ) 
//             return false;
//     }
//     return true;
// }

void Backtrack(int t){
    if(t>n){ 
        if(minweight > nowweight){
            minweight = nowweight;
            for(int i=1; i<=n; i++){ 
                y[i] = x[i];
            }
        }
    }
    for(int i=1; i<=m; i++){
        if(nowweight + w[t][i] < minweight && cost + c[t][i] <= d){ 
            x[t] = i; 
            nowweight += w[t][i];
            cost += c[t][i];
//             if(place(t))
            Backtrack(t+1);
            nowweight -= w[t][i];
            cost -= c[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];
        }
    }
    nowweight = 0;
    cost = 0;
    Backtrack(1);
    cout<<minweight<<endl;
    for(int i=1; i<=n; i++){
        cout<<y[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说明 “最小重量机器设计问题"的解空间树

 

 

 

2.对回溯算法的理解

(1)回溯法

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

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

(2)剪枝函数:

一般回溯法会走剪枝函数,因为你回溯了,已经走了这个步骤,走过处理的逻辑,当前节点的数据存在参与计算。你退回上一步,则需要减去当前步骤的数据是吧。编写去除这些节点数据的函数就是剪枝函数。