1. 程式人生 > >揹包問題的C語言實現

揹包問題的C語言實現


    自打師哥佈置了揹包問題的作業之後,雖然看了不少次,但每次不是因為時間太緊,要不就是太難了老想逃避,一直沒解決這個問題。終於藉著學校運動會,抓緊時間看了看C語言揹包問題的實現,動態規劃還是太難,只好先從C入手來解決理解一下。當時師哥提到這個揹包問題的時候,我並沒理解這個問題的意思,師哥給的資料是:一個容量為10的揹包,四個物品重量分別為5463;價值為1040305;求這個揹包可容納物品的最大價值?具體我當時的心理活動現在已經忘了,我只記得當時的確是理解錯了,沒明白什麼意思。後來又去網上百度,百度的解釋如下:

揹包問題(Knapsack problem)是一種組合優化的NP完全問題

。問題可以描述為:給定一組物品,每種物品都有自己的重量和價格,在限定的總重量內,我們如何選擇,才能使得物品的總價格最高。問題的名稱來源於如何選擇最合適的物品放置於給定揹包中。相似問題經常出現在商業、組合數學,計算複雜性理論、密碼學和應用數學等領域中。也可以將揹包問題描述為決定性問題,即在總重量不超過W的前提下,總價值是否能達到V?它是在1978年由MerkelHellman提出的。

揹包問題已經研究了一個多世紀,早期的作品可追溯到1897 數學家托比亞斯·丹齊格(Tobias Dantzig1884-1956)的早期作品 ,並指的是包裝你最有價值或有用的物品而不會超載你的行李的常見問題。

揹包問題的應用:

 1998年石溪布魯克演算法庫發現在75個演算法問題中,揹包問題是第18個最受歡迎,第4個最需要解決的問題。各種領域的決策問題都會出現,如尋找最少的浪費來削減原材料,選擇投資和投資組合,選擇資產支援資產證券化,和生成金鑰為和其他揹包密碼系統。

揹包問題的定義:

我們有n種物品,物品j的重量為wj,價格為pj

我們假定所有物品的重量和價格都是非負的。揹包所能承受的最大重量為W

如果限定每種物品只能選擇0個或1個,則問題稱為0-1揹包問題

如果不限定每種物品的數量,則問題稱為無界揹包問題。

各類複雜的揹包問題總可以變換為簡單的0-1揹包問題進行求解。

      記得剛讀完百科的解釋後,我想著可不可以把每個物品是否要都考慮一遍,然後全排列,看看哪種情況是正確的,後來這種做法直接被否定了,因為早考慮的情況太多,當物品非常多的時候,有可能就無法進行了。後來聽同學說,考慮一件物品的去留,當時我是懷疑的,因為當從一件開始考慮時我認為這件物品和其他物品的關聯就斷了,也就是說你不能考慮整體的,可當真正開始處理的時候才明白,從一個物品開始,一個個考慮,是揹包問題

C語言解決的思路。

#include"stdio.h"
#define MAX 20
 
int Min(int x, int y)
{
return x <= y ? x : y;
}
 
int Max(int x, int y)
{
return x >= y ? x : y;
}
 
void TraceBack(int (*middle)[MAX], int *weight, int column, int length, int *x)
{
int i;
for(i = 1; i < length; i++)
if(middle[i][column] == middle[i + 1][column])
x[i] = 0;
else
{
x[i] = 1;
column -= weight[i];
}
x[length] = (middle[length][column] ? 1 : 0);
}
 
void Knapsack(int *value, int *weight, int column, int length, int (*middle)[MAX])
{
int i, j, jMax = Min(weight[length] - 1, column);
for(j = 0; j <= jMax; j++)//從最後一個開始觀察,因為最後一個程式碼沒有前面值,所以需要單獨寫
 
middle[length][j] = 0;
for(j = weight[length]; j <= column; j++)
middle[length][j] = value[length];
for(i = length - 1; i > 1; i--)//中間的程式碼一個一個單獨敲
{
jMax = Min(weight[i] - 1, column);
for(j = 0; j <= jMax; j++)
middle[i][j] = middle[i + 1][j];
for(j = weight[i]; j <= column; j++)
middle[i][j] = Max(middle[i + 1][j], middle[i + 1][j - weight[i]] + value[i]);
}
middle[1][column] = middle[2][column];//最後的一組可以不考慮前面的情況,直接考慮最後他自己是否需要加入就可以
if(column >= weight[1])
middle[1][column] = Max(middle[1][column], middle[2][column - weight[1]] + value[1]);
}
 
int main(void)
{
int i, length, column, count = 0, wj[MAX], pj[MAX], x[MAX] = {0}, middle[MAX][MAX] = {0};
printf("請輸入揹包總容量:\n");
scanf("%d", &column);
printf("請輸入物品個數:\n");
scanf("%d", &length);
/*if(length < 1)
{
printf("輸入錯誤!!!\n");
return;
}//判斷*/
for(i = 1; i <= length; i++)
{
printf("請輸入第%d個物品的重量及價值:\n", i);
scanf("%d %d", wj + i, pj + i);//為什麼不在0開始
}
Knapsack(value, wj, column, length, middle);
TraceBack(middle, wj, column, length, x);
printf("Result:\n");
for(i = 1; i <= length; i++)
if(x[i])
printf("Number: %d, ", i);
printf("\n");
}

相關推薦

01揹包問題(用c語言實現)-回溯法求解

回溯法求解01揹包   用回溯法解問題時,應明確定義問題的解空間。問題的解空間至少應包含問題的一個(最優)解。例如,對於有n種可選擇物品的0-1揹包問題,其解空間由長度為n的0-1向量組成。該解空間

[演算法]簡單的揹包問題遞迴解法,C語言實現

今天講點簡單的演算法,最簡單的揹包0演算法,使用了遞迴的方法,相信看完程式碼的朋友會發現這段程式碼很熟悉,不過CG提供這些程式碼的目的只是讓全部揹包演算法的完整提供地給大家,程式碼很簡單,相信高手一看就懂,這裡的揹包演算法只是考慮了物品的重量,沒有考慮物品的價值,是初學遞迴演算法的朋友必看的程式碼,高手的話全

揹包問題的C語言實現

    自打師哥佈置了揹包問題的作業之後,雖然看了不少次,但每次不是因為時間太緊,要不就是太難了老想逃避,一直沒解決這個問題。終於藉著學校運動會,抓緊時間看了看C語言揹包問題的實現,動態規劃還是太難,只好先從C入手來解決理解一下。當時師哥提到這個揹包問題的時候,我並沒理

0-1揹包問題(動態規劃C語言實現

#include <stdio.h> #include <stdlib.h> #define WEIGHT 10 #define NUM 5 int main() { int w[NUM + 1] = {0,2,2,6,5,4}; int p[

[演算法]揹包問題的經典演算法和貪心演算法解答,C語言實現

聖誕前夜講點比較具有聖誕感覺的演算法,揹包問題演算法,這裡我寫了經典演算法和貪心演算法兩種解決方法,因為時間不多,所以給出的陣列是已經排序的,因為貪心演算法可能要用得到,經典演算法因為是一個一個比較,因此排序也就沒有那麼重要了,可能兩種演算法的最終執行效果一樣的,朋友們除錯的時候記得修改我給出的測試陣列,今天

01揹包c語言實現

        01揹包算是動態規劃的入門專案了,網上的解釋也是各種爛大街。題目基本是下面這種格式的:         01揹包是在M件物品取出若干件放在空間為W的揹包裡,每件物品的體積為W1,W2……Wn,與之相對應的價值為P1,P2……Pn。(來自百度百科)    

二十四進制編碼串轉換為32位無符號整數(C語言實現

bool while open 參數錯誤 hint div 第一個字符 bsp opened typedef int BOOL; #define TRUE 1; #define FALSE 0; #define UINT_MAX 0xffffffff

遺傳算法的C語言實現(二)

print 比較 詳細 author 當前 cross max r+ 訪問 上一次我們使用遺傳算法求解了一個較為復雜的多元非線性函數的極值問題,也基本了解了遺傳算法的實現基本步驟。這一次,我再以經典的TSP問題為例,更加深入地說明遺傳算法中選擇、交叉、變異等核心步

C語言實現粒子群算法(PSO)二

計算 default img 第一個元素 1.4 best 實驗 atl 說過 上一回說了基本粒子群算法的實現,並且給出了C語言代碼。這一篇主要講解影響粒子群算法的一個重要參數---w。我們已經說過粒子群算法的核心的兩個公式為: Vid(k+1)=w*Vid(k)+c1*r

遺傳算法的C語言實現(一):以非線性函數求極值為例

選中 algorithm 利用 mail 進化 lock gcc 最大值 -s 以前搞數學建模的時候,研究過(其實也不算是研究,只是大概了解)一些人工智能算法,比如前面已經說過的粒子群算法(PSO),還有著名的遺傳算法(GA),模擬退火算法(SA),蟻群算法(A

C語言實現粒子群算法(PSO)一

mat 遺傳 基於 [1] 沒有 實驗 規模 直觀 解決 最近在溫習C語言,看的書是《C primer Plus》,忽然想起來以前在參加數學建模的時候,用過的一些智能算法,比如遺傳算法、粒子群算法、蟻群算法等等。當時是使用MATLAB來實現的,而且有些MATLAB自帶了工具

(續)順序表之單循環鏈表(C語言實現)

include 作者 指針 順序 gb2 mark oos case 循環 單循環鏈表和單鏈表的唯一差別在於單循環鏈表的最後一個節點的指針域指向第一個節點, 使得整個鏈表形成一個環. C實現代碼例如以下: #include<stdio.h>

geek青年的狀態機,查表,純C語言實現

fill south 總結 target 堅持 str 分享 接收 backward geek青年的狀態機,查表,純C語言實現 1. 問題的提出。抽象 建一,不止是他,不少人跟我討論過這種問題:怎樣才幹保證在需求變更、擴充的情況下。程序的主體部分不動呢? 這是一個

C語言實現數據結構串(堆分配存儲表示法)

+= 賦值 size ++ fine hello n) clu 刪除字符串 ———————————————————————————————————————————— 堆分配存儲表示法 —————————————————————————————————————————

帶頭節點的單鏈表-------C語言實現

lib gmail spa 階段 c語言實現 fun 變化 尾插 mail 1 /***************************************************** 2 Author:Simon_Kly Version:0.1

排序(3)---------冒泡排序(C語言實現)

std 強調 tracking i++ oid printf pre rand() 執行 說到冒泡排序,大一的時候第一次學習這個排序算法,可能大家不知道,“冒泡”在我說的方言裏面是吹牛逼的意思。所以就認為這個排序算法特吹牛逼有木有。 相信大家對全部的排

數據結構之---C語言實現廣義表頭尾鏈表存儲表示

tle substring [1] 原子 depth ring else if max sig //廣義表的頭尾鏈表存儲表示 //楊鑫 #include <stdio.h> #include <malloc.h> #include <std

C語言實現中綴表達式轉後綴表達式

ctype 結束 錯誤 ini c語言實現 base color src 格式 代碼如下: #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define STACK

C語言實現推排序

poi sort log ren -- eof parent class tdi KeyPoint : 找到關鍵的父節點      單線程找最大值 最快的方法 #include "stdlib.h" #include "stdio.h" void findMax(int

C語言實現單鏈表節點的刪除(帶頭結點)

data art pos grand urn ria tps move sni 我在之前一篇博客《C語言實現單鏈表節點的刪除(不帶頭結點)》中具體實現了怎樣在一個不帶頭結點的單鏈表的刪除一個節點,在這一篇博客中我改成了帶頭結點的單鏈表。代碼演示樣例上傳至 h