【算法设计与分析】实验7:复杂装载及0/1背包问题的回溯法设计与求解

news2025/2/3 1:45:30

目录

一、实验目的

二、实验环境

三、实验内容

四、核心代码

五、记录与处理

六、思考与总结

七、完整报告和成果文件提取链接

一、实验目的

        针对复杂装载问题、及0/1背包问题开展分析、建模、评价,算法设计与优化,并进行编码实践。

        理解复杂装载问题及0/1背包问题的回溯法求解策略,能够对比分析与动态规划求解复杂装载问题的策略差异;能够根据具体的问题进行解空间树的构造及剪枝函数设计;针对如上两个问题利用回溯法进行设计求解,并进行对比两个问题求解时的异同。并利用JAVA/C/C++等编程语言将算法转换为对应的程序上机运行(语言自选)。

二、实验环境

        1、机房电脑  Window10

        2、Eclipse /DEVC++等

三、实验内容

实验要求:

1、掌握回溯法进行问题分析及建模的过程;

2、复杂装载、及0/1背包问题能够利用回溯法开展算法设计与优化;

(1)复杂装载问题背景:指定两艘船容量C1,C2,给定n个货物,各物品重量wi已知。请问是否可以成功装入两艘船,及如何选择物品分别装入两艘船?

(2)0/1背包问题背景:指定背包容量C,给定n个商品,各商品重量wi、价值vi已知。如何选择商品,使得装入背包的价值最大?

3、能够对上述问题的回溯法进行时间复杂性分析,并与动态规划进行对比。

【回溯法原理】

        回溯法是一种暴力搜索方法,它将问题的解表示为n元组(x1, x2, …, xn)的形式。其核心在于逐步构建一个解空间,过程中涉及选择、判断及必要的回退步骤,直至找到问题的解或确认无解。这种求解思路类似于逐步探索的过程,一旦当前路径不满足求解条件,便“回溯”以尝试其他路径。

       解决一个问题的所有可能的决策序列就是解空间。

       对于回溯法解决的问题而言,它的解空间一般用树或图的形式来组织,即为解空间树,树的每一个结点确定每个问题的一个状态。树的根结点代表初始状态,以下每一层代表所作出的选择。

       由于回溯法解决的问题较为冗杂,情况复杂,所以用回溯法搜索解空间时,通常采用两种策略避免无效搜索,提高回溯的搜索效率。

实验原理:

1、针对复杂装载背包问题,如何利用回溯法进行算法设计

【装载方案】

(1)首先将第一艘轮船尽可能装满;

(2)然后将剩余的集装箱装在第二艘轮船上;

将第一艘轮船尽可能装满等价于选取全体集装箱的一个子集,在承载范围内,使该子集中集装箱重量之和最大。

复杂装载问题的解空间是一个子集树

【求解思路】

(1) 将尽可能多的集装箱装到第一艘船上

(2) 约束条件判断:cw + w[i] <= c,判断当前路径是否可以装载当前集装箱 i 而不超过船的最大承载能力 c

(3) 剪枝函数(限界条件):cw + r >bestw,判断当前路径是否有可能超过已知的最佳装载重量 bestw。

(4) 终止条件判断:当i>n时,说明已经遍历到叶子节点,此时判断cw > bestw,这个条件的作用是判断当前路径的装载重量 cw 是否超过了已知的最佳装载重量 bestw,如果满足则需要更新 bestw 为当前的装载重量 cw。

利用回溯法求解时:在最坏情况下,每个集装箱都有两个选择(装或不装),因此递归树的分支因子为 2。因此,递归树的最大深度为 n,每层最多有两个分支。最坏情况时间复杂度是O( ),剪枝策略的存在,会使实际运行时间通常会低于这个值,回溯法的空间复杂度为 O(n)

采用动态规划算法时,时间复杂度为动态规划算法O(nc) ,最优空间复杂度为O(c)

 一般情况下使用动态规划算法解决复杂装载问题的时间复杂度更优。

2、针对0/1背包问题,如何利用回溯法进行算法设计

【装载方案】

背包容量限制:每次选择物品时,必须确保当前背包中的物品总重量不超过背包容量 c。

物品选择限制:每个物品只能选择一次(0/1背包问题)。

最优解要求:在所有满足约束条件的解中,选择总价值最大的解。

【求解思路】

(1) 将尽可能多的价值高的装到背包中

(2) 约束条件判断:cw + w[i] <= c,该条件用于判断当前物品是否可以被选择。

(3) 剪枝函数(限界条件):剪枝函数 bound 用于计算当前解的上界,以决定是否继续搜索某个分支。cp+rp>bestp

(4) 终止条件判断:条件:i > n,当所有物品都已经考虑完毕时, i 超过物品数量 n时,检查当前解的价值 cp 是否大于已知的最佳价值 bestp。如果当前解更好,则更新最佳价值 bestp 并记录当前解 bestx。

对于0/1背包问题,回溯法方法求解时,计算上界需要O(n)时间,在最坏情况下有O( )个右儿子结点需要计算上界,所以时间复杂度为O( ),回溯法求解的空间复杂度为O(n)。

采用动态规划算法时,时间复杂度为O(nc) ,最优空间复杂度为O(c)

一般情况下使用动态规划算法解决0/1背包问题的时间复杂度更优。

3、针对同一问题,对比动态规划及回溯法求解的算法复杂度。

1.利用回溯法求解时:在最坏情况下,每个集装箱都有两个选择(装或不装),因此递归树的分支因子为 2。因此,递归树的最大深度为 n,每层最多有两个分支。最坏情况时间复杂度是O(2n ),剪枝函数会使实际运行时间通常会低于这个值,回溯法求解的空间复杂度为O(n)。

采用动态规划算法时,时间复杂度为O(nc) , 最优空间复杂度为O(c)

       一般情况下使用动态规划算法解决复杂装载问题的时间复杂度更优。

对于0/1背包问题,回溯法方法求解时,计算上界需要O(n)时间,在最坏情况下有O(2n )个右儿子结点需要计算上界,所以时间复杂度为O(n2n ),回溯法求解的空间复杂度为O(n)。

采用动态规划算法时,时间复杂度为O(nc) ,最优空间复杂度为O(c)

一般情况下使用动态规划算法解决0/1背包问题的时间复杂度更优。

四、核心代码

// 回溯函数,用于搜索所有可能的解
void backtrack(int i) {
    if (i > n) { // 如果已经考虑完所有物品
        if (cp > bestp) { // 如果当前价值大于已知最佳价值
            bestp = cp; // 更新最佳价值
            for (int j = 1; j <= n; j++) {
                bestx[j] = x[j]; // 记录最佳解
            }
        }
        return;
    }
    // 搜索左子树:选择当前物品
    if (cw + w[i] <= c) {
        x[i] = 1; // 标记选择当前物品
        cw += w[i]; // 更新当前重量
        cp += p[i]; // 更新当前价值
        backtrack(i + 1); // 递归处理下一个物品
        cw -= w[i]; // 回溯,恢复当前重量
        cp -= p[i]; // 回溯,恢复当前价值
    }
    // 搜索右子树:不选择当前物品
    if (bound(i + 1) > bestp) { // 只有当上界大于已知最佳价值时才继续搜索
        x[i] = 0; // 标记不选择当前物品
        backtrack(i + 1); // 递归处理下一个物品
    }
}
void backtrack(int i) {        //搜索深度为i的结点 
    if (i > n) {            // 如果所有货物都考虑完毕
        if (cw1 + cw2 > bestw) {    // 如果当前装载的总重量大于已知的最优解
            bestw = cw1 + cw2;        // 更新最优解的重量
            for (int j = 0; j <= n; ++j) {
                bestx[j] = x[j];    // 保存当前的装载方案
            }
        }
        return;
    }
    // 尝试将第i个物品放入第一艘船
    if (cw1 + w[i] <= C1 && cw1 + r1 > bestw) {
        x[i] = 1;
        cw1 += w[i];     // 更新第一艘船的装载重量
        r1 -= w[i];        // 更新剩余重量
        backtrack(i + 1);
        cw1 -= w[i];    // 回溯,恢复状态
        r1 += w[i];
    }
}

五、记录与处理

1、复杂装载问题实验数据及结果分析。

当输入C1=50,C2=50,w={10,40,40}时,所有货物都装进去了,最优装载量为90

2、0/1背包问题实验数据及结果分析。

六、思考与总结

通过本次实验,我对回溯法有了更深刻的理解。回溯法通过递归的方式,逐步构建问题的解空间,并在搜索过程中使用剪枝函数来避免无效搜索,从而提高搜索效率。这种方法在解决组合优化问题时非常有效,尤其是在解决解空间较小或可以通过剪枝显著减少搜索空间的一类问题时。

七、完整报告和成果文件提取链接

完整可运行代码以及相关实验报告以下链接可获取:
链接: https://pan.baidu.com/s/1iss6-C2nxZQGkEpo-WDn0A?pwd=g5cg 提取码: g5cg 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2291039.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

仿真设计|基于51单片机的温湿度、一氧化碳、甲醛检测报警系统

目录 具体实现功能 设计介绍 51单片机简介 资料内容 仿真实现&#xff08;protues8.7&#xff09; 程序&#xff08;Keil5&#xff09; 全部内容 资料获取 具体实现功能 &#xff08;1&#xff09;温湿度传感器、CO传感器、甲醛传感器实时检测温湿度值、CO值和甲醛值进…

使用vhd虚拟磁盘安装两个win10系统

使用vhd虚拟磁盘安装两个win10系统 前言vhd虚拟磁盘技术简介准备工具开始动手实践1.winX选择磁盘管理2.选择“操作”--“创建VHD”3.自定义一个位置&#xff0c;输入虚拟磁盘大小4.右键初始化磁盘5.选择GPT分区表格式6.右键新建简单卷7.给卷起个名字&#xff0c;用于区分8.打开…

深入理解Spring事务管理

一、事务基础概念 1.1 什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09;是数据库操作的最小工作单元&#xff0c;具有ACID四大特性&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;事务中的操作要么全部成功&#xff0c;要么全部失败 一致…

自制虚拟机(C/C++)(二、分析引导扇区,虚拟机读二进制文件img软盘)

先修复上一次的bug&#xff0c;添加新指令&#xff0c;并增加图形界面 #include <graphics.h> #include <conio.h> #include <windows.h> #include <commdlg.h> #include <iostream> #include <fstream> #include <sstream> #inclu…

ASP.NET Core 启动并提供静态文件

ASP.NET Core 启动并提供静态文件 即是单个可执行文件&#xff0c;它既运行 API 项目&#xff0c;也托管 前端项目&#xff08;通常是前端的发布文件&#xff09;。 这种方式一般是通过将 前端项目 的发布文件&#xff08;例如 HTML、CSS、JavaScript&#xff09;放入 Web AP…

4 [危机13小时追踪一场GitHub投毒事件]

事件概要 自北京时间 2024.12.4 晚间6点起&#xff0c; GitHub 上不断出现“幽灵仓库”&#xff0c;仓库中没有任何代码&#xff0c;只有诱导性的病毒文件。当天&#xff0c;他们成为了 GitHub 上 star 增速最快的仓库。超过 180 个虚假僵尸账户正在传播病毒&#xff0c;等待不…

变量和常量

一.变量 1.标准声明 var 变量名 变量类型 变量声明行末不需要分号 2..批量声明 package main import "fmt" func main(){var(a string b int c boold float32)}3.变量的初始化 var a int 10 var b float321.1 4.类型推导 var name"tom" var age18 fmt.Pr…

大模型概述(方便不懂技术的人入门)

1 大模型的价值 LLM模型对人类的作用&#xff0c;就是一个百科全书级的助手。有多么地百科全书&#xff0c;则用参数的量来描述&#xff0c; 一般地&#xff0c;大模型的参数越多&#xff0c;则该模型越好。例如&#xff0c;GPT-3有1750亿个参数&#xff0c;GPT-4可能有超过1万…

流浪 Linux: 外置 USB SSD 安装 ArchLinux

注: ArchLinux 系统为滚动更新, 变化很快, 所以本文中的安装方法可能很快就过时了, 仅供参考. 实际安装时建议去阅读官方文档. 最近, 突然 (也没有那么突然) 有了一大堆 PC: 4 个笔记本, 2 个台式主机 (M-ATX 主板), 1 个小主机 (迷你主机). 嗯, 多到用不过来. 但是, 窝又不能…

Hot100之子串

560和为K的子数组 题目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列 思路解析 ps&#xff1a;我们的presum【0】就是0&#xff0c;如果没有这个0的话我们的第一个元素就无法减去上…

网络工程师 (11)软件生命周期与开发模型

一、软件生命周期 前言 软件生命周期&#xff0c;也称为软件开发周期或软件开发生命周期&#xff0c;是指从软件项目的启动到软件不再被使用为止的整个期间。这个过程可以细分为多个阶段&#xff0c;每个阶段都有其特定的目标、任务和产出物。 1. 问题定义与需求分析 问题定义…

(三)QT——信号与槽机制——计数器程序

目录 前言 信号&#xff08;Signal&#xff09;与槽&#xff08;Slot&#xff09;的定义 一、系统自带的信号和槽 二、自定义信号和槽 三、信号和槽的扩展 四、Lambda 表达式 总结 前言 信号与槽机制是 Qt 中的一种重要的通信机制&#xff0c;用于不同对象之间的事件响…

hot100_21. 合并两个有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#xff1a;[…

安全防护前置

就业概述 网络安全工程师/安全运维工程师/安全工程师 安全架构师/安全专员/研究院&#xff08;数学要好&#xff09; 厂商工程师&#xff08;售前/售后&#xff09; 系统集成工程师&#xff08;所有计算机知识都要会一点&#xff09; 学习目标 前言 网络安全事件 蠕虫病毒--&…

01-六自由度串联机械臂(ABB)位置分析

ABB工业机器人&#xff08;IRB2600&#xff09;如下图所示&#xff08;d1444.8mm&#xff0c;a1150mm&#xff0c;a2700mm&#xff0c;a3115mm&#xff0c;d4795mm&#xff0c;d685mm&#xff09;&#xff0c;利用改进DH法建模&#xff0c;坐标系如下所示&#xff1a; 利用改进…

JVM运行时数据区域-附面试题

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域 有各自的用途&#xff0c;以及创建和销毁的时间&#xff0c;有的区域随着虚拟机进程的启动而一直存在&#xff0c;有些区域则是 依赖用户线程的启动和结束而建立和销毁。 1. 程序计…

HTML(快速入门)

欢迎大家来到我的博客~欢迎大家对我的博客提出指导&#xff0c;有错误的地方会改进的哦~点击这里了解更多内容 目录 一、前言二、HTML基础2.1 什么是HTML?2.2 认识HTML标签2.2.1 HTML标签当中的基本结构2.2.2 标签层次结构 2.3 HTML常见标签2.3.1 标题标签2.3.2 段落标签2.3.3…

《苍穹外卖》项目学习记录-Day10订单状态定时处理

利用Cron表达式生成器生成Cron表达式 1.处理超时订单 查询订单表把超时的订单查询出来&#xff0c;也就是订单的状态为待付款&#xff0c;下单的时间已经超过了15分钟。 //select * from orders where status ? and order_time < (当前时间 - 15分钟) 遍历集合把数据库…

AJAX综合案例——图书管理

黑马程序员视频地址&#xff1a; AJAX-Day02-10.案例_图书管理AJAX-Day02-10.案例_图书管理_总结_V1.0是黑马程序员前端AJAX入门到实战全套教程&#xff0c;包含学前端框架必会的&#xff08;ajaxnode.jswebpackgit&#xff09;&#xff0c;一套全覆盖的第25集视频&#xff0c…

30.Word:设计并制作新年贺卡以及标签【30】

目录 NO1.2 NO3邮件合并-信函 NO4邮件合并-标签​ NO1.2 另存为/F12&#xff1a;考生文件夹&#xff1a;Word.docx布局→页面设置对话框→页边距&#xff1a;上下左右→纸张&#xff1a;宽度/高度&#xff08;先调页边距&#x1f197;&#xff09;设计→页面颜色→填充效果→…