近似裝箱問題(三種聯機算法實現)


【0】README

0.1) 本文總結於 數據結構與算法分析, 源代碼均為原創, 旨在 理解 “近似裝箱問題(三種聯機算法實現)” 的idea 並用源代碼加以實現;
0.2) 近似裝箱問題的三種聯機算法 分別是: 下項適合算法 + 首次適合算法 + 最佳適合算法 , 我們將依次給出源代碼實現+算法描述;
0.2)聯機問題+脫機問題

  • version1)聯機裝箱問題: 在這種問題中, 必須將每一件物品放入一個箱子后才處理下一件物品;(英語口語考試, 做完上一題,才能進入下一題作答)
  • version2)脫機裝箱問題:在一個脫機裝箱算法中, 我們做任何事情 都需要等到所有的輸入數據全被讀入后才進行;(一般的考試,你只需要在規定的時間做完題目即可,做題順序不是我們所關心的)

【1】近似裝箱問題

1.1)問題描述: 給定N 項物品, 大小為 s1, s2, ..., sN, 所有的大小都滿足 0 < si < = 1 ;問題是要把這些物品裝到最小數目的箱子中去, 已知每個箱子的容量是1個單位;下圖顯示的是 對N項物品的最優裝箱方法;
這里寫圖片描述
1.2)有兩種版本的裝箱問題:

  • version1)聯機裝箱問題: 在這種問題中, 必須將每一件物品放入一個箱子后才處理下一件物品;(英語口語考試, 做完上一題,才能進入下一題作答)
  • version2)脫機裝箱問題:在一個脫機裝箱算法中, 我們做任何事情 都需要等到所有的輸入數據全被讀入后才進行;(一般的考試,你只需要在規定的時間做完題目即可,做題順序不是我們所關心的)

1.3)聯機算法

  • 1.3.1)要考慮的第一個問題是: 一個聯機算法即使在允許無限計算的情況下是否實際上總能給出最優的解答;我們知道, 即使允許無限計算, 聯機算法也必須先放入一項物品然后才能處理下一件物品並且不能改變決定
  • 1.3.2)我們可以證明:聯機算法不總能夠給出最優解;

【2】下項適合算法

2.1)算法描述: 當處理任一物品時, 我們檢查看他是否還能裝進剛剛裝進物品的同一個箱子中去。 如果能夠裝進去, 那么就把它裝入該箱子中, 否則,就開辟一個新箱子;
2.2)看個荔枝:
這里寫圖片描述


2.3)source code + printing results

void nextfix(double key, int* index)
{
	int i;
	ElementTypePtr box;
	ElementTypePtr temp;

	box = buildSingleElement();
	box->key = key; // build single box with key over
	
	i = *index;
	for(; i<size; i++)
	{
		if(surplus[i] < key)
			continue;
		temp = boxes[i]	;
		while(temp->next)					
			temp = temp->next;
		temp->next = box;
		surplus[i] -= key;
		break;
	}
	*index = i;
}
  • 2.3.3)printing results:
    這里寫圖片描述

【3】首次適合算法

3.0)出現的問題:雖然下項算法有一個合理的性能保證,但是,它的效果在實踐中是很差的,因為在不需要開辟新箱子的時候它卻開辟了新箱子;
3.1)算法描述:首次適合算法的策略是 依序掃描這些箱子但吧新的一項物品放入足夠盛下它的第一個箱子中。因此,只有當先前放置物品的結果已經沒有再容得下當前物品余地的時候, 我們才開辟一個新箱子;(一句話, 這里是從頭到尾掃描箱子)
3.2)看個荔枝:
這里寫圖片描述
3.3)可以斷言:首次適合算法保證其解最多包含最優裝箱數的二倍;因為在任一時刻最多有一個箱子其空出的部分大於箱子的一半,因為若有第二個這樣的箱子, 則它裝的物品就會裝到第一個這樣的箱子中了;
3.4)source code + printing results

void firstFix(double key)
{
	int i;
	ElementTypePtr box;
	ElementTypePtr temp;

	box = buildSingleElement();
	box->key = key; // build single box with key over

	for(i=0; i<size; i++)
	{
		if(surplus[i] < key)
			continue;
		temp = boxes[i]	;
		while(temp->next)					
			temp = temp->next;
		temp->next = box;
		surplus[i] -= key;
		break;
	}
}
  • 3.4.3)printing results:
    這里寫圖片描述

【4】最佳適合算法

4.1)算法描述:該方法不是吧一項新物品放入所發現的第一個能夠容納它的箱子, 而是放到所有箱子中能夠容納它的最滿的箱子中;
4.2)看個荔枝:
這里寫圖片描述
Attention)

  • A1)大小為0.3 的項不是放在B2 而是放在了B3, 此時它正好把B3填滿;
  • A2)當需要O(NlogN)的時候, 該算法對隨機的輸入表現得很好;

4.3)source code + printing results

void bestFix(double key)
{
	int i;
	ElementTypePtr box;
	ElementTypePtr temp;
	double minimum;
	int miniIndex;

	box = buildSingleElement();
	box->key = key; // build single box with key over
	miniIndex = 0;
	minimum = 1.0;

	for(i=0; i<size; i++)
	{
		if(surplus[i] < key)
			continue;
		if(surplus[i] - key < minimum)
		{
			minimum = surplus[i] - key;
			miniIndex = i;
		}
	}

	temp = boxes[miniIndex]	;
	while(temp->next)					
		temp = temp->next;
	temp->next = box;
	surplus[miniIndex] -= key;	
}
  • 2.3)printing results:
    這里寫圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM