c_cpp 有一批共Ñ个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱我的重量为WI,装载问题要求确定是否有一个合理的装载方案可将这些集装箱装上这2艘轮船。如果有,找出一种装载方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp 有一批共Ñ个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱我的重量为WI,装载问题要求确定是否有一个合理的装载方案可将这些集装箱装上这2艘轮船。如果有,找出一种装载方案相关的知识,希望对你有一定的参考价值。

//递归回溯
#include "stdafx.h"
#include <iostream>
using namespace std; 
 
template <class Type>
class Loading
{
	//friend Type MaxLoading(Type[],Type,int,int []);
	//private:
	public:
		void Backtrack(int i);
		int n,			//集装箱数
            *x,			//当前解
			*bestx;		//当前最优解
			Type *w,	//集装箱重量数组
			c,			//第一艘轮船的载重量
			cw,			//当前载重量
			bestw,		//当前最优载重量
			r;          //剩余集装箱重量
};
 
template <class Type>
void  Loading <Type>::Backtrack (int i);
 
template<class Type>
Type MaxLoading(Type w[], Type c, int n, int bestx[]);
 
int main()
{   
	int n=3,m;
	int c=50,c2=50;
 
	int w[4]={0,10,40,40};
	int bestx[4];
 
    m=MaxLoading(w, c, n, bestx);
 
	cout<<"轮船的载重量分别为:"<<endl;
	cout<<"c(1)="<<c<<",c(2)="<<c2<<endl;
 
	cout<<"待装集装箱重量分别为:"<<endl;
	cout<<"w(i)=";
	for (int i=1;i<=n;i++)
	{
		cout<<w[i]<<" ";
	}
	cout<<endl;
 
	cout<<"回溯选择结果为:"<<endl;
	cout<<"m(1)="<<m<<endl;
	cout<<"x(i)=";
 
	for (int i=1;i<=n;i++)
	{
		cout<<bestx[i]<<" ";
	}
	cout<<endl;
 
	int m2=0;
	for (int j=1;j<=n;j++)
	{
		m2=m2+w[j]*(1-bestx[j]);
	}
   	cout<<"m(2)="<<m2<<endl;
 
	if(m2>c2)
	{
		cout<<"因为m(2)大于c(2),所以原问题无解!"<<endl;
	}
	return 0;
}
 
template <class Type>
void  Loading <Type>::Backtrack (int i)// 搜索第i层结点
{
	if (i > n)// 到达叶结点
	{  
		if (cw>bestw)
		{
			for(int j=1;j<=n;j++) 
			{
				bestx[j]=x[j];//更新最优解
				bestw=cw; 
			}
		} 
		return;
	}
 
	r-=w[i]; 
	if (cw + w[i] <= c) // 搜索左子树
	{ 
		x[i] = 1;
		cw += w[i];
		Backtrack(i+1);
		cw-=w[i];    
	}
 
	if (cw + r > bestw)
	{
		x[i] = 0;  // 搜索右子树
		Backtrack(i + 1);  
	}
	r+=w[i]; 
}
 
template<class Type>
Type MaxLoading(Type w[], Type c, int n, int bestx[])//返回最优载重量
{
	Loading<Type>X;
	//初始化X
	X.x=new int[n+1];
	X.w=w;
	X.c=c;
	X.n=n;
	X.bestx=bestx;
	X.bestw=0;
	X.cw=0;
	//初始化r
	X.r=0;
 
	for (int i=1;i<=n;i++)
	{
		X.r+=w[i];
	}
 
	X.Backtrack(1);
	delete []X.x;
	return X.bestw;
}
//迭代回溯
#include "stdafx.h"
#include <iostream>
using namespace std; 
 
template<class Type>
Type MaxLoading(Type w[ ], Type c, int n, int bestx[ ]);
 
int main()
{   
	int n=3,m;
	int c=50,c2=50;
	int w[4]={0,10,40,40};
	int bestx[4];
 
    m=MaxLoading(w, c, n, bestx);
 
	cout<<"轮船的载重量分别为:"<<endl;
	cout<<"c(1)="<<c<<",c(2)="<<c2<<endl;
 
	cout<<"待装集装箱重量分别为:"<<endl;
	cout<<"w(i)=";
	for (int i=1;i<=n;i++)
	{
		cout<<w[i]<<" ";
	}
	cout<<endl;
 
	cout<<"回溯选择结果为:"<<endl;
	cout<<"m(1)="<<m<<endl;
	cout<<"x(i)=";
 
	for (int i=1;i<=n;i++)
	{
		cout<<bestx[i]<<" ";
	}
	cout<<endl;
 
	int m2=0;
	for (int j=1;j<=n;j++)
	{
		m2=m2+w[j]*(1-bestx[j]);
	}
   	cout<<"m(2)="<<m2<<endl;
 
	if(m2>c2) 
	{
		cout<<"因为m(2)大于c(2),所以原问题无解!"<<endl;
	}
	return 0;
}
 
 
template <class Type>
Type MaxLoading(Type w[],Type c,int n,int bestx[])//迭代回溯法,返回最优载重量及其相应解,初始化根结点
{
	int i=1;//当前层,x[1:i-1]为当前路径
	int *x=new int[n+1];
 
	Type bestw=0,      //当前最优载重量
		 cw=0,         //当前载重量
		 r=0;          //剩余集装箱重量
 
	for (int j=1;j<=n;j++)
	{
		r+=w[j];
	}
 
	while(true)//搜索子树
	{     
		while(i<=n &&cw+w[i]<=c)//进入左子树
		{
			r-=w[i];
			cw+=w[i];
			x[i]=1;
			i++;
		}
		
		if (i>n)//到达叶结点
		{      
			for (int j=1;j<=n;j++)
			{
				bestx[j]=x[j];
			}
			bestw=cw;
		}
		else//进入右子树
		{          
			r-=w[i];
			x[i]=0; i++;
		}
		while (cw+r<=bestw)
		{ //剪枝回溯
			i--;   
			while (i>0 && !x[i])
			{ 
				r+=w[i];
				i--;
			}   
			//从右子树返回
			if (i==0)
			{
				delete []x;
				return bestw;
			}
			x[i]=0;
			cw-=w[i];
			i++;
		} 
	}  
}

以上是关于c_cpp 有一批共Ñ个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱我的重量为WI,装载问题要求确定是否有一个合理的装载方案可将这些集装箱装上这2艘轮船。如果有,找出一种装载方案的主要内容,如果未能解决你的问题,请参考以下文章

回溯算法 - 最优装载

装载问题回溯法

尽可能装满的背包问题

装载问题,0-1背包

最优装载(贪心)

最优装载