一、题目

★问题描述:设某一机器由 n n n个部件组成,每一种部件都可以从 m m m个不同的供应商处购得。设 w ij w_{\text{ij}} wij​是从供应商 j j j处购得的部件 i i i的重量, c ij c_{\text{ij}} cij​是相应的价格。

试设计一个算法,给出总价格不超过 c c c的最小重量机器设计。

★算法设计:对于给定的机器部件重量和机器部件价格,计算总价格不超过 d d d的最小机器重量设计。

★数据输入:由文件input.txt给出输入数据。第一行有3个正整数 n , m , d n,m,d n,m,d。接下来的2 n n n行,每行 n n n个数。前 n n n行是 c c c,后 n n n行是 w w w。

★结果输出:将计算的最小重量及每个部件的供应商输出到文件output.txt。

输入文件示例 输出文件示例

input.txt
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

二、题目解析

1、设计分析

题目是一个组合优化问题,解决此类问题可以考虑使用贪心算法、动态规划、回溯与分支限界算法。对于本题,如果使用贪心算法,每种部件都选择重量最小的供应商,显然会因为没有考虑价格而导致无法正确求解。另外,由于本题不符合优化原则即当选择 n n n种部件时的最优解不一定是选择 n + 1 n + 1 n+1种部件时的最优解,所以不能使用动态规划算法。由于本题符合多米诺性质即如果某一选择方案选择了 n n n个部件时不符合约束条件,那么无论第 n + k ( k > 0 ) n + k(k > 0) n+k(k>0)种部件如何选择,该选择方案都不符合约束条件,所以可以使用回溯算法,同时为了加快回溯速度,以下解法采用了分支限界技术。

解题过程: 共 n n n种部件, m m m个供应商,总价格不超过 d d d,设每个供应商的编号分别为 1 , 2 , 3 ⋅ ⋅ ⋅ , m 1,2,3 \cdot \cdot \cdot ,m 1,2,3⋅⋅⋅,m,

搜索空间为 { < x 1 , x 2 , x 3 , ⋅ ⋅ ⋅ x n > ∣ x i ∈ N , 1 ≤ x i ≤ m } \left\{ < x_{1},x_{2},x_{3}, \cdot \cdot \cdot x_{n} > \ \right|\ x_{i} \in N,1 \leq x_{i} \leq m\} {<x1​,x2​,x3​,⋅⋅⋅xn​> ∣ xi​∈N,1≤xi​≤m}, x i x_{i} xi​的值表示第 i i i个部件的供应商编号。

约束条件:所有部件的总价格 ≤ d \leq d ≤d.

界: 当前已经得出的所有可行解对应的重量的最小值

代价函数: 当前已经选择的部件总重量 + + +剩余部件(不考虑价格)可能的最小重量即结

点 < x 1 , x 2 , x 3 , ⋅ ⋅ ⋅ , x k > < x_{1},x_{2},x_{3}, \cdot \cdot \cdot ,x_{k} > <x1​,x2​,x3​,⋅⋅⋅,xk​>处代价函数的值为

F k = ∑ i = 1 k − 1 c i x i + ∑ i = k n w i ′ F_{k} = \sum_{i = 1}^{k - 1}c_{ix_{i}} + \sum_{i = k}^{n}w_{i}^{'} Fk​=∑i=1k−1​cixi​​+∑i=kn​wi′​

其中 c ij c_{\text{ij}} cij​为第 i i i个部件从第 j j j个供应商处购买的价格, w i ′ w_{i}^{'} wi′​为第 i i i个部件的最低价格

搜索策略:深度优先

在根结点处,没有选择任何部件,总重量和总价格都为 0 0 0,代价函数的值为所有部件的最低价格之和,界函数的初值为无穷大,代价函数小于界函数,所以往下搜索根结点的 m m m个分支。对于所有结点,都进行如下操作:

①判断当前结点代价函数的值是否大于界函数,如果是,则回溯。

②(分支限界)判断是否满足约束条件,如果不满足则回溯。

③如果在①和②处都没有回溯,则继续向下搜索 m m m个分支

如果搜索到叶子结点,即得到一个可行解,则将其与界函数比较,如果可行解对应的总重量小于界函数,则将界函数的值更新为该可行解对于的总重量,记录对于的供应商选择方案,然后回溯。

实例:

源代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
/*
n:部件数量
m:供应商数量
d:最大总价格
使用分支限界算法搜索策略:深度优先搜索树:树中的结点可表示为序列<X1,X2,X3···,Xn>,其
中Xi表示第i个部件选择的供应商编号(1<=Xi<=m)约束条件:总价格小于d界:当前已经求出的总价格<=d的最小重量和代价函数:当前已经选择的部件总重量+剩余部件(不考虑价格)可能的最小重量
*/
#define MAX 100
int cost[MAX][MAX],weight[MAX][MAX],minSum[MAX];
int result[MAX], tempResult[MAX];
int n, m, d, minWeight = 99999, curWeight = 0, curCost = 0;
/*
cost[i][j]:第i个部件从第j个供应商购买的价格
weight[i][j]:第i个部件从第j个供应商购买的重量
minSum[i]:不考虑价格,后(n-i)个部件的最小重量和result[i]:储存第i个部件的供应商编号
tempResult[i]:在求解过程中储存第i个部件的供应商编号n:部件的总数
m:供应商数量
minWeight:最小重量(目标函数)
curWeight:记录当前(已选部件)的总重量
curCost:记录当前(已选部件)的总价格
*/
void setMinSum()//计算minSum数组的值
{//minSum[i]:不考虑价格,后(n - i)个部件的最小重量和for (int i = n; i >=1; i--){//后(n - i)个部件的最小重量和=后(n - i-1)个部件的最小重量和+第(n-i)个部件的最小重量minSum[i]=minSum[i+1]+ *(min_element(weight[i]+1, weight[i] + 1+m));/*printf("w%d:%d\n ",i, *(weight[i] + 3));printf("min:%d\n ", *(min_element(weight[i] + 1, weight[i] + m)));printf("sum:%d \n", minSum[i]);*/}
}void Reback(int k)//求价格<=d的第k~n个部件最小重量和
{/*从搜索树的第k层开始搜索*/if (k == 1){/*从第1层搜索时先初始化MinSum函数,便于之后计算代价函数*/setMinSum();}if (k > n)//到达叶子结点(所有部件都已选择完毕){if (curWeight < minWeight)//当前的重量和<已经求出的的最小重量和{minWeight = curWeight;//更新最小重量和for (int i = 1; i <= n; i++){result[i] = tempResult[i];//更新每个部件的供应商编号}}return;//到达叶子结点,回溯}else{if (minSum[k] + curWeight > minWeight){/*代价函数:剩余部件的最小重量和+当前已选部件重量和界函数:当前已经求出的最小重量和当代价函数>界函数,直接回溯*/return;}for (int i = 1; i <= m; i++)//循环搜索选择第m个供应商的情况{if (curCost + cost[k][i] <= d)//如果总价格小于d{curWeight += weight[k][i];//当前总重量加上第k个部件从第i个供应商购买的重量curCost += cost[k][i];//当前总价格加上第k个部件从的第i个供应商购买的价格tempResult[k] = i;//记录第k个部件的供应商编号Reback(k + 1);//递归,求价格<=d的第k+1~n个部件最小重量搜索//在下一次循环前先将重量和价格恢复原状curWeight -= weight[k][i];curCost -= cost[k][i];}}}
}int main()
{FILE* fr = fopen("./input.txt", "r");fscanf(fr, "%d%d%d", &n, &m, &d);//从input.txt中读取n,m,dfor (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){fscanf(fr,"%d", &cost[i][j]);//读取第i个部件从的j个供应商购买的价格}}for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){fscanf(fr,"%d", &weight[i][j]);//读取第i个部件从的j个供应商购买的重量//printf("%d%d :%d   ",i,j,weight[i][j]);}}fclose(fr);Reback(1);//求价格<=d的1~n个部件的最小重量和FILE* fw = fopen("./output.txt", "w");fprintf(fw, "%d\n", minWeight);//将最小重量和输出到output.txtfor (int i = 1; i <= n; i++){//将每个部件的供应商编号输出的output.txtfprintf(fw,"%d ", result[i]);}fclose(fw);//打印结果printf("最小重量: %d\n", minWeight);printf("各部件供应商:");for (int i = 1; i <= n; i++){printf("%d ", result[i]);}printf("\n");return 0;
}

三、测试实例

input-1
8 18 14
18 15 20 5 15 10 16 6 1 6 17 6 1 2 17 15 13 17
16 6 7 4 7 2 11 6 18 4 13 12 8 5 2 8 15 14
12 6 19 10 13 8 2 10 16 4 15 15 16 13 17 12 14 4
18 18 2 13 15 19 5 12 18 7 13 9 8 17 10 13 15 11
8 5 14 11 18 20 17 3 11 17 13 11 4 9 17 14 19 1
10 7 8 11 13 3 19 3 12 11 12 14 4 2 12 10 14 15
12 9 13 9 16 17 12 15 6 3 11 17 13 17 14 13 4 4
19 12 3 19 3 20 19 12 8 19 8 10 19 20 3 1 7 1
16 12 4 16 2 6 15 1 13 3 7 16 5 3 16 16 14 19
12 14 6 2 11 15 9 17 15 16 19 20 14 14 20 9 4 4
6 13 16 6 3 12 12 19 11 20 4 13 9 18 7 17 8 1
4 17 3 20 3 8 12 7 4 12 6 12 1 18 13 20 20 8
4 15 1 10 2 12 8 11 5 4 20 13 12 20 1 3 3 11
1 9 2 1 16 1 12 4 5 2 7 15 12 3 9 4 13 6
13 1 10 8 5 13 20 10 6 4 8 15 8 8 20 11 9 9
2 10 11 1 18 8 20 11 18 2 3 6 14 16 19 4 3 15
output-1
57
13 6 7 3 18 14 10 16

intput-2(贪心算法会出错)
3 3 6
1 2 3
2 4 1
2 2 2
1 2 3
3 1 2
2 2 2
output-2
5
1 3 1

最小重量机器设计问题(回溯-分支限界)相关推荐

  1. 用回溯法解决最小重量机器设计问题

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

  2. 最小重量机器设计问题

    原文章:https://www.cnblogs.com/henuliulei/p/10188305.html 问题描述 设某一机器由n个部件组成,每一种部件都可以从m个不同的供应商处购得.设wij是从 ...

  3. 分支限界法求解最小重量机器问题

    #include<iostream> #include<queue> #define INF 65535 #define MAXNUM 100 using namespace ...

  4. 0x08算法设计与分析复习(二):算法设计策略-回溯法2

    参考书籍:算法设计与分析--C++语言描述(第二版) 算法设计策略-回溯法 子集和数 问题描述 已知n个不同的正数wi(0≤i≤n−1)的集合,求该集合的所有满足条件的子集,使得每个子集中的正数之和等 ...

  5. 最小拍有纹波系统仿真实验matlab代码,最小拍控制器设计.doc

    最小拍控制器设计matlab实验 [实验目的] 了解和掌握有纹波和无纹波最小拍控制器的原理和设计方法. 利用Matlab仿真,观察系统的输入输出曲线. [实验内容] 系统如图所示, G(s)?-R( ...

  6. 伺服电机选型计算pdf_机器设计中伺服电机及驱动器的选型(PDF),文末附下载地址...

    在当前的机器设计中,我们面临着提高效率,节能降耗,可靠稳定和降低成本的挑战.如何正确选择驱动器和伺服电机成为设计机器是否能够达到工艺要求,同时满足最佳能量匹配的重要因素,关于这个问题不管是网络上还是市 ...

  7. 最小拍无差控制器MATLAB求解,最小拍控制器设计.doc

    最小拍控制器设计.doc 最小拍控制器设计 matlab 实验实验目的1 了解和掌握有纹波和无纹波最小拍控制器的原理和设计方法.2 利用 Matlab仿真,观察系统的输入输出曲线.实验内容系统如图所示 ...

  8. STM32教程(4)-最小系统的设计

    什么是最小系统呢?就是芯片可以真正工作所需的必要的硬件系统.如果只是把一个芯片放在你面前,你跟它说:来,输出个占空比百分之五十的正 弦波.当然不能输出,这是毫无疑问的.那还需要什么呢? --电源电路的 ...

  9. 从美术设计角度回溯与展望CODM出海之路

    2021年10月8日,由腾讯游戏学院举办的第四届腾讯游戏开发者大会(Tencent Game Developers Conference,简称TGDC)进入了第二天的议程.来自腾讯互动娱乐天美J3工作 ...

最新文章

  1. C语言实现DES,3DES以及基于3DES的文件加密系统
  2. 20145220韩旭飞《网络对抗》Exp6 信息搜集与漏洞扫描
  3. EBS R12.2 ADOP (R12.2 AD Online Patching) - 5
  4. Superset单点登录调整源码
  5. 蔚来汽车发布声明:“蔚来EC6爆炸”为谣言
  6. WinForm程序启动时不显示主窗体的实现方法
  7. linux笔记:linux帮助命令,man,help,whatis,apropos
  8. 前端项目集成 stylelint
  9. php操作elasticsearch
  10. [ 搭建Redis本地服务器实践系列二 ] :图解CentOS7配置Redis
  11. 3种方法设置PPT文件保护
  12. char字符变量在c语言中有什么用,c语言char怎么用
  13. php开发幸运大转盘,jQuery幸运大转盘_jQuery+PHP抽奖程序
  14. 语法错误与语义错误(所有语言通用版)
  15. 2022 最新版java开发手册 黄山版
  16. Android 保持屏幕不熄屏
  17. 什么是分布式数据存储
  18. 【精】【PDF链接转图片】- Java用pdfbox将PDF的URL转换并压缩成图片,解决“口口口”乱码问题
  19. 解决无法找到winRAR.exe
  20. android ratingbar不可点击,RatingBar是无法点击的

热门文章

  1. [GDOI模拟2015.08.12]囚人的旋律
  2. Synology Drive Client 提示用户名/密码无效或用户权限不足
  3. Qt:QChart绘图介绍(主要包含类:QChart,QTableWidget,QGridLayout)
  4. 小米颓势已现,生死劫命悬手机
  5. 02--2017年同济大学824通信原理复习总结
  6. EasyAR 开发技巧----截屏
  7. jdk8銝要onematch_JDK 8 新特性之函数式编程 → Stream API
  8. 2021 年度总结——平安喜乐
  9. Linux放大缩小字体的快捷键
  10. nuxt解决首屏加载慢问题_天涯明月刀手游腾讯手游助手 PC端 卡加载,无法登陆问题 解决方案...