一 问题描述:有一批共个集装箱要装上2艘载重量分别为C1和C2的轮船,其中集装箱i的重量为Wi,且装载问题要求确定是否有一个合理的装载方案可将这个集装箱装上这2艘轮船。如果有,找出一种装载方案。
容易证明:如果一个给定装载问题有解,则采用下面的策略可得到最优装载方案。
(1)首先将第一艘轮船尽可能装满;
(2)将剩余的集装箱装上第二艘轮船。
二:
(1)解决装载问题的优先队列,将扩展节点的当前装载的重量(Ew)加上剩余集装箱的总重量 (r[i]) 作为优先级,从优先级队列中出队列。
(2)为了方便找到最优的分配方法,在每一个节点设置指向父节点的指针,当算法走到第 n+1层就可以停止寻找,因为当前扩展节点队列 而 i = n+1 时,说明了当前的优先级 uweight最高,就是说 Ew +r[n+1]最大,而r[n+1] =0 , 所以Ew要大于队列中剩余的所有的Ew +r[i] ;
#include <iostream>
#include <algorithm>
using namespace std;
template <typename T>
class MaxHeap{
public:
MaxHeap(int cap);
bool insert(T value);
bool remove(T value);
void print();
bool createMaxHeap(T *a,int length);
T getTop();
void filterup(int index);
void filterdown(int start,int end);
int size;
private:
int capacity;
T *heap;
};
template <typename T>
MaxHeap<T>::MaxHeap(int cap):capacity(cap),size(0),heap(NULL){
heap = new T[capacity];
};
template <typename T>
T MaxHeap<T>::getTop(){
if(size != 0){
size--;
T temp = heap[0];
heap[0] = heap[size];
filterdown(0,size);
return temp;
}
}
template <typename T>
void MaxHeap<T>::print(){
for(int i = 0; i < size;i++){
cout<<heap[i];
if(i == size-1)
cout<<endl;
else
cout<<" ";
}
}
template <typename T>
bool MaxHeap<T>::createMaxHeap(T *a,int length){
if(length > capacity)
return false;
for(int i = 0; i < length;i++)
heap[i] = a[i];
size = length;
int currentPos = (size-2)/2;
while(currentPos >= 0){
filterdown(currentPos,size-1);
currentPos--;
}
return true;
}
template <typename T>
void MaxHeap<T>::filterup(int start){
int j = start;
if(j == 0)
return;
int i = (start-1)/2;
T temp = heap[start];
while( j > 0){
if(heap[i]<= temp){
heap[j] = heap[i];
j = i;
i = (i-1)/2;
}else
break;
}
heap[j] = temp;
}
template<typename T>
void MaxHeap<T>::filterdown(int start,int end){
int i = start;
int j = i*2 + 1;
T temp = heap[i];
if(j > size-1)
return;
while( i <= end){
if(j > size-1)
break;
if(j + 1 <=size-1 && heap[j] < heap[j+1])
j++;
if(temp > heap[j])
break;
else{
heap[i] = heap[j];
i = j;
j = 2*i+1;
}
}
heap[i] = temp;
}
template <typename T>
bool MaxHeap<T>::remove(T value){ //删除节点
bool judge = false;
for(int i = 0; i < size;i++){
if(heap[i] == value){
heap[i] = heap[size-1];
size--;
filterdown(i,size);
judge = true;
}
}
return judge;
}
template <typename T>
bool MaxHeap<T>::insert(T value){
if(size == capacity){
cout<<"Heap full"<<endl;
return false;
}
heap[size] = value;
filterup(size);
size++;
return true;
}
template <typename Type>class HeapNode;
class TNode{
public:
friend bool AddactiveNode(MaxHeap<HeapNode<int> >&,TNode*,int ,bool ,int );
friend int Maxloading(int w[],int ,int ,bool *);
private:
TNode *father;
bool lchild;
};
template <typename Type>class HeapNode{
public:
friend bool AddactiveNode(MaxHeap<HeapNode<int> >&,TNode*,int ,bool ,int );
friend int Maxloading(int w[],int,int ,bool *);
operator Type()const{
return uweight;}
friend bool operator <=(const HeapNode &a,const HeapNode &b){
return a.uweight < b.uweight;
}
private:
TNode *ptr;
Type uweight;
int level;
};
bool AddactiveNode(MaxHeap<HeapNode<int> >&H,TNode *E,int wt,bool ch,int lev){//向队列中插入一个节点
TNode *node = new TNode;
node->lchild = ch;
node->father = E;
HeapNode<int>op;
op.ptr = node;
op.uweight = wt;
op.level = lev;
H.insert(op);
return true;
}
int Maxloading(int w[],int c,int n,bool bestx[]){
int *r;
r = new int[n+1];
r[n] = 0; //数组r[i]用来记录第i个集装箱之后的总重量 (不包括第i个集装箱的重量)
for(int j = n-1; j >= 0;j--)
r[j] = r[j+1] + w[j+1];
MaxHeap<HeapNode<int> >H(100000);
int i =1; //扩展节点初始为第1层
int bestw = 0;
TNode *E = 0; //指向扩展节点的指针
int Ew = 0; //扩展节点的当前装载为Ew
while(i!=n+1){ //到达第n+1层就停止
if(Ew + w[i] <= c)
//添加左孩子
AddactiveNode(H,E,Ew+w[i]+r[i],true,i+1); //左孩子标记true
//添加右孩子
AddactiveNode(H,E,Ew+r[i],false,i+1); //右孩子标记false
HeapNode<int>T;
//更新扩展节点
T = H.getTop(); //得到优先级最高的节点,并删除这个节点
i = T.level;
E = T.ptr;
Ew = T.uweight - r[i-1];
}
for(int j = n;j >0;j--){ //根据左孩子标记判断是否装入
bestx[j] = E->lchild;
E = E->father;
}
return Ew;
}
int main(){
int w[7] = { 0,1,2,3,4,5,6};
int aw = 0;
for(int i = 0;i < 7;i++)
aw +=w[i];
int c1 = 19;
int c2 = 20;
bool bestxp[7];
int w1 = Maxloading(w,c1,6,bestxp);
if(c2 < aw - w1)
return false;
for(int i = 1;i < 7;i++){
if(bestxp[i] == true)
cout<<"第"<<i<<"件物品"<<"装入轮船1"<<endl;
else if(bestxp[i] == false)
cout<<"第"<<i<<"件物品"<<"装入轮船2"<<endl;
}
return 0;
}