天天看點

貪婪算法-----裝箱問題

貪婪算法

  • 貪婪準則
    • 算法在推進的過程中,每一步都追求最優解
    • 貪婪準則一旦确定,中途不能改變
  • 貪婪算法求出的最終解不一定是最優解

裝箱問題

  • 問題描述:有若幹個體積為V的箱子,有n個體積為V0,V1,V2,V3…Vn-1的物品
  • 要求:把所有物品都裝入箱子中,使打開的箱子盡可能少
  • 解決思路
    • 貪婪準則
      • 将所有物品按體積的降序排序
      • 每次取出一個物品(目前未裝入物品的體積最大值)
      • 周遊所有已打開的箱子,将物品放入最早打開的箱子
    • 存儲形式:連結清單
      貪婪算法-----裝箱問題
    • 類型聲明

      1.排序物品體積時物品的類型

typedef struct{
	int gno;//物品編号
	int gv;//物品體積
}ElemG;
           
2.裝箱時物品的類型
           
typedef struct node{
	int gno;//物品編号
	struct node* link;//指向下一個節點的指針域
}GoodsLink;
           
3.箱子節點
           
typedef struct box{
	int Reminder;//存放箱子剩餘體積
	GoodsLink *hg;//指向物品的位址
	struct box* next;//指向下一個箱子的指針域
}EBOX;
           
  • 算法描述

    1.建立物品資訊,并初始化

ElemG* Init_Goods(){
	int v[N] = {3,2,5,8,10,1,6,12,19,4}; //物品的體積 
	
	ElemG *g;
	g = (ElemG *)malloc((N)*sizeof(ElemG));//存儲物品的數組 
	for(int i=0;i<N;i++){
		//初始化物品 
		g[i].gno = i;
		g[i].gv = v[i];
	}
	return g; 
}
           

2.把所有物品體積按照降序的順序排序

//将儲存物品的進行降序排序 (使用快排)
void GoodsSort(ElemG *g,int left,int right){
	ElemG temp;
	 
	if(left > right){
		return;
	}else{
		int base = g[left].gv;
		int i = left;
		int j = right;
		while(i != j){
			while(base >= g[j].gv && i<j){
				j--;
			}
			
			while(base <= g[i].gv && i<j){
				i++;
			}
			if(i < j){
				temp = g[i];
				g[i] = g[j];
				g[j] = temp;
			}
		}
		temp = g[left];
		g[left] = g[i];
		g[i] = temp;
		
		GoodsSort(g,left,i-1);
		GoodsSort(g,i+1,right);
	}
}
           

3.裝箱

EBox* Load(ElemG* g){
	//初始化箱子 
	EBox* hBox,*tail;//hBox指向頭結點,tail指向尾節點 
	hBox = tail = NULL;
	
	//開始裝箱 
	for(int i=0;i<N;i++){
		EBox* p;
		for(p = hBox;p && p->Reminder<g[i].gv;p = p->next);
		
		//定義裝箱時物品節點并初始化 
		GoodsLink* gl = (GoodsLink*)malloc(sizeof(GoodsLink)); 
		gl->gno = g[i].gno;
		gl->link = NULL;
		
		if(!p){
			//建立箱子節點并初始化
			p = (EBox*)malloc(sizeof(EBox));
			p->hg = gl;
			p->next = NULL;
			p->Reminder = V-g[i].gv;
			//挂箱子(區分頭結點和中間節點) 
			if(!hBox){
				hBox = tail = p;
			}else{
				tail ->next = p;
				tail = p;
			}
		}else{
			//将物品放置到已建立的箱子
			p->Reminder = p->Reminder - g[i].gv;
			GoodsLink* a = p->hg;
			while(a->link != NULL){
				a = a->link;
			}
			a->link = gl;
		}
	}
	return hBox;
}
           

4.輸出

//輸出 
void print(EBox* hBox){
	EBox* p = hBox;
	GoodsLink* gl;
	while(p){
		printf("箱子剩下的體積:%d--",p->Reminder);
		printf("---箱子裝的物品編号:");
		for(gl = p->hg;gl;gl = gl->link){
			printf("%d,",gl->gno);
		}
		printf("\n");
		
		p = p->next;
	}
}

           

繼續閱讀