关于装箱问题的算法研究

本文研究装箱问题,通过模拟退火和遗传算法进行求解。介绍了两种算法的思路,并对性能进行了分析,讨论了算法在不同物品数量情况下的表现。尽管目前实现的效果不尽如人意,作者表示会继续优化。
摘要由CSDN通过智能技术生成

装箱问题的算法研究

山东大学 赵一帆

问题描述

在箱子装载问题中,有若干个容量为c的箱子和n个待装载入箱子中的物品。物品i需占s[i]个单元(0<s[i]≤c)。所谓成功装载(feasible packing),是指能把所有物品都装入箱子而不溢出,而最优装载(optimal packing)则是指使用了最少箱子的成功装载。

问题分析

这道题目是算法课设发给我要求完成的题目,给了四种基本的算法,再加上avl树和竞赛树优化(竞赛树那部分我写的还是有点满意),后续我感觉可以用模拟退火来做一下,所以就搜集资料尝试了一下,之后百度百科说遗传算法也可以做,所以就自己想象凭空捏造了一波遗传算法,欢迎指出不足点。
其实这两种思路都是有更有目标和优化的搜索而已。

模拟退火思路

每次交换50个rand()对,如果替换结果就保留这个交换,否则不保留,不停在函数上面溜达,其实我也不知道这个函数长什么样子。

遗传算法思路

之前没有搞过这个算法,先学的,感觉很多二手博客非常不尊重达尔文同志的思想,强行忽略了遗传中很多的步骤,也有可能是他们生物没有学的很好,所以我加上了染色体交叉互换的环节,一共有n*(n/32)个染色体,每个染色体上面有32个基因,每个基因表示i和j是否进行交换,1表示为显性,0表示为隐形,这样空间最多可以表达<1000的数量,可惜最后进化效果并不是很好,大概进化的时间还是太短了,或者说这道题本身可能就不是很适合进化,因为箱子的交换有可能会走向好的方向,但是保留之后并不能显然的确定会向更好的方向进行移动。

性能分析

可以发现我写的退火算法和遗传算法确实不咋地,有时间再改进改进把,但是实际上我感觉真的挺难优化的。

大物品情况:
答案:
源数据1答案
运行时间:
源数据1时间复杂度
1000物品
时间比对
时间比对
中等物品情况下:
答案:
答案
运行时间:

中物品
时间对比1
时间对比2
小物品:
答案:
答案
运行时间:
时间

优化
小物品
小物品

模拟真实数据:

代码分析

void FF()
{
   
	LL startTime = clock();
	int hasNumber = 0;
	for(int i = 1;i <= n;++i)	
	{
   
		bool flag = false;
		for(int j = 1;j <= hasNumber&&!flag;++j)
		{
   
			if(c_has[j] >= s[i]) 
			{
   
				c_has[j] -= s[i];
				flag = true;
			}
		}
		if(!flag) c_has[++hasNumber] = c - s[i];	
	}
	cout<<"最先匹配法耗时"<<clock()-startTime<<"毫秒,";
	cout<<"消耗箱子"<<hasNumber<<"个"<<endl; 
}
int FFCT(int mode)	//竞赛树做法 
{
   
	LL startTime = clock(),hasNumber = 0;
	for(int i = 1;i <= 2*n;++i) cmt[i] = c;
	for(int i = 1;i <= n;++i)
	{
   
		int x = 1;
		while(x < n) {
   
			if(cmt[x * 2] >= s[i]) x = x * 2;
			else x = x * 2 + 1;
		}
		cmt[x] -= s[i];
		while(x > 1) {
   
			x = x/2;
			cmt[x] = max(cmt[x*2],cmt[x*2 + 1]);
		}
	}
	for(int i = n;i <= 2 * n - 1;++i) 
		if(cmt[i] != c) hasNumber++;
	if(mode == 0)
	{
   
		cout<<"最先匹配(竞赛树优化)法耗时"<<clock()-startTime<<"毫秒,";
		cout<<"消耗箱子"<<hasNumber<<"个"<<endl; 
	}
	return hasNumber;
}

void FFD()
{
   
	LL startTime = clock();
	int hasNumber = 0;
	for(int i = 1;i <= n;++i) s_max[i] = s[i];
	sort(s_max+1,s_max+n+1,cmp);
	for(int i = 1;i <= n;++i)	
	{
   
		bool flag = false;
		for(int j = 1;j <= hasNumber&&!flag;++j)
		{
   
			if(c_has[j] >= s_max[i]) 
			{
   
				c_has[j] -= s_max[i];
				flag = true;
			}
		}
		if(!flag) c_has[++hasNumber] = c - s_max[i]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值