1.箱子装载问题:箱子的数量不限,每个箱子的容量为binCapacity,待装载的物品有n个,物品i需要占用的箱子容量为objectSize[i]。所谓可行装载,是指所有物品装入箱子而不溢出。所谓最优装载是指使用箱子最少的可行装载。
2.最先适配法(first fit,FF):物品按1,2,3,…n的顺序装入箱子。假设箱子从左到右排列。每个物品i放入可装载它的最左面的箱子。
最优适配法(best fit,BF):物品i放入可用容量最小但不小于oblectSize[i]的箱子。
最先适配递减法:所有物品先递减排序,然后再使用FF.
最优适配递减法:所有物品先递减排序,然后再使用BF.
3 用赢者树实现最先适配法原理:
首先将箱子数组初始化为一颗赢者树,然后每次寻找其左子树(因为我们要将物品放到最左边的箱子),当左子树根节点的箱子容量大于物品容量时,说明左子树存在能装载物品的箱子,然后再寻找左子树的左子树,在对其进行同样的判断,直到外部节点。如果左子树不存在可用箱子,则节点数目加1转战当前根节点的右兄弟,即上一层根节点的右子树,然后对该右子树进行寻找左子树的操作直到根节点。
代码实现:
void firstFitPack(int *objectSize,int numberOfObject,int binCapacity)
{
int n=numberOfObject;//物品数量
//初始化n个箱子和赢者树
binType *bin=new binType [n+1];//binType是一个结构体只有一个unUsedcapacity数据,还有实现了结构体之间的比较函数
for(int i=1;i<=n;i++)
bin[i].unusedCapacity=binCapacity;//将数组里面的元素全部初始化为箱子的初始容量
completeWinnerTree<binType>winTree(bin,n)//将数组初始化为一颗赢者树
//将物品装到箱子里面
for(int i=1;i<=n;i++)
{//把物品i装到一个箱子
//找到第一个有足够容量的箱子
int child=2;//从根的左孩子开始搜索
while(child<n)
{
int winner=winTree.winner(child);//获取child节点里面装载的箱子标签
if(bin[winner].unusedCapacity<objectSize[i])
child++;//如果左子树没有满足条件的箱子则转移到右子树
child*=2;//沿着左子树一路向下寻找,直到child>n即外部节点
}
int binToUse;
child/=2; //撤销至外部节点的父节点
if(child<n)//如果撤销到了内部节点
{
binToUse=winTree.winner(child);//将外部节点的父节点所存的那个箱子作为最终选择的箱子
if(binToUse>1&&bin[binToUse-1].unusedCapacity>=objectSize[i])
binToUse--;//有可能左右两个外部节点都满足条件,但是右外部节点是胜者,所以我们最后的比较左右两个外部节点保证最后选中的是最左边的外部节点
}
else//这句没搞清楚
binToUse=winTree.winner(child/2);
cout<<"Pack object"<<i<<"in bin"<<binToUse<<endl;
bin[binToUse].unusedCapacity-=objectSize[i];//更新容量
winTree.rePlay(binToUse);//重赛
}
}