贪心算法实现装箱问题
实验要求
实验 2:装箱问题
[实验目的]
1. 练习贪婪法求解
2. 练习链表的使用
[实验题目]
装箱问题可简述如下:设有编号为 0、1、…、n-1 的 n 种物品,体积分别为
v0、v1、…、vn-1。将这 n 种物品装到容量都为 V 的若干箱子里。约定这 n 种物品的
体积均不超过 V,即对于 0≤i<n,有 0<vi≤v。不同的装箱方案所需要的箱子数
目可能不同。装箱问题要求使装尽这 n 种物品的箱子数要少。
[算法分析]
贪婪法是一种不追求最优解,只希望得到较为满意解的方法。贪婪法一般可
以快速得到满意的解,因为它省去了为找最优解要穷尽所有可能而必须耗费的大
量时间。贪婪法常以当前情况为基础作最优选择,而不考虑各种可能的整体情况,
所以贪婪法不要回溯。
例如平时购物找钱时,为使找回的零钱的硬币数最少,不考虑找零钱的所有
各种发表方案,而是从最大面值的币种开始,按递减的顺序考虑各币种,先尽量
用大面值的币种,当不足大面值币种的金额时才去考虑下一种较小面值的币种。
这就是在使用贪婪法。这种方法在这里总是最优,是因为银行对其发行的硬币种
类和硬币面值的巧妙安排。如只有面值分别为 1、5 和 11 单位的硬币,而希望找
回总额为 15 单位的硬币。按贪婪算法,应找 1 个 11 单位面值的硬币和 4 个 1 单
位面值的硬币,共找回 5 个硬币。但最优的解应是 3 个 5 单位面值的硬币。
若考察将 n 种物品的集合分划成 n 个或小于 n 个物品的所有子集,最优解就
可以找到。但所有可能划分的总数太大。对适当大的 n,找出所有可能的划分要花
费的时间是无法承受的。为此,对装箱问题采用非常简单的近似算法,即贪婪法。
该算法依次将物品放到它第一个能放进去的箱子中,该算法虽不能保证找到最优
解,但还是能找到非常好的解。不失一般性,设 n 件物品的体积是按从大到小排
好序的,即有 v0≥v1≥…≥vn-1。如不满足上述要求,只要先对这 n 件物品按它们
的体积从大到小排序,然后按排序结果对物品重新编号即可。装箱算法简单描述
如下:
{
输入箱子的容积;
输入物品种数 n;
按体积从大到小顺序,输入各物品的体积;
预置已用箱子链为空;
预置已用箱子计数器 box_count 为 0;
for
(i=0;i<n;i++)
{
从已用的第一只箱子开始顺序寻找能放入物品 i
的箱子 j;
if
(已用箱子都不能再放物品 i)4
{
另用一个箱子,并将物品 i 放入该箱子;
box_count++;
}
else
将物品 i 放入箱子 j;
}
}
实现代码
装箱问题

import java.util.*; public class box { public static void main(String[] args) { ArrayList<Integer> weight = new ArrayList<>(); // 存放物品重量的 ArrayList<Integer> x = new ArrayList<>(); //存放是否取出 Integer box = 0; ArrayList<Integer[]> boxx = new ArrayList<>(); // 存放具体的物品 int i = 0; //第几位 Integer V = 0; // 箱子重量 Scanner sc = new Scanner(System.in); //将箱子重量赋值 System.out.println("请输入箱子的容积:"); V = Integer.valueOf(sc.next()); box = V; //输入物品重量 System.out.println("请输入物品的重量(结束请按'0'):"); while (true) { if (sc.hasNext()) { int num = sc.nextInt(); if (num == 0) { break; } weight.add(num); x.add(1); } } System.out.println("----------"); sort(weight); System.out.println("物体重量为:"); for (Integer j : weight) { System.out.print(j + " "); } IN(weight,box,boxx); int size = boxx.size(); for (int j = 0; j < size; j++) { Integer[] values = boxx.get(j); System.out.println(); System.out.println("方法"+j+"为:"); for (int k = 0; k < values.length; k++) { System.out.print(" -- " + values[k] + " -- "); } } } /** * * @param weight 剩余的箱子的重量 * @param box 箱子的容积 * @param boxx 装入箱子的分组 */ private static void IN(ArrayList<Integer> weight,Integer box,ArrayList<Integer[]> boxx) { if (weight.size() == 0){ return; } ArrayList<Integer> x = new ArrayList<>(); //添加数组 Integer boxcopy = box; int k = weight.size(); //不能用Itero迭代器,会出bug的,只能用for循环,使用数组删除也不行,会将重复的数据全部删除 for (int i = 0,j = 0;i < k ;i++){ if (box >= weight.get(j) ){ box -= weight.get(j); x.add(weight.get(j)); weight.remove(j); }else{ j++; } } boxx.add(become_In(x)); IN(weight,boxcopy,boxx); } /** * 排序,将sort方法进行重写,变成从大到小 * @param weight */ private static void sort(ArrayList<Integer> weight) { weight.sort(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { if (o1 > o2) { //从大到小 return -1; } else { return 1; } } }); } /** * 将arraylist转换为integer【】 * @param x 传入的需要转换形式的数组 * @return 返回值 */ private static Integer[] become_In(ArrayList<Integer> x){ Integer[] arr = x.toArray(new Integer[x.size()]); return arr; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器