日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

01背包问题的动态规划求解及其C++实现

發(fā)布時(shí)間:2023/12/29 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 01背包问题的动态规划求解及其C++实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文講解01背包問(wèn)題的動(dòng)態(tài)規(guī)劃求解,并使用C++進(jìn)行了實(shí)現(xiàn)

文章目錄

  • 01背包問(wèn)題
  • 動(dòng)態(tài)規(guī)劃
  • 01背包問(wèn)題的動(dòng)態(tài)規(guī)劃求解
  • 01背包問(wèn)題的動(dòng)態(tài)規(guī)劃求解-C++實(shí)現(xiàn)

01背包問(wèn)題

nnn個(gè)物品,這些物品的重量分別為w1,w2,...,wnw_1,w_2,...,w_nw1?,w2?,...,wn?,價(jià)值分別為v1,v2,...,vnv_1,v_2,...,v_nv1?,v2?,...,vn?.

現(xiàn)給定一個(gè)背包,背包的容量為CCC,要求從這個(gè)nnn個(gè)物品中選擇一些物品裝進(jìn)背包,讓背包盡可能裝滿,并使得背包里裝的物品的價(jià)值最大。

要從這些物品中挑選一些裝進(jìn)背包,對(duì)于某一物品而言,只有裝和不裝兩種選擇,因此稱為01背包問(wèn)題

動(dòng)態(tài)規(guī)劃

動(dòng)態(tài)規(guī)劃是一種算法設(shè)計(jì)技術(shù),它用來(lái)解決類似這樣的問(wèn)題:

一個(gè)問(wèn)題可以被分成很多個(gè)階段,而且任何一階段的行為都依賴于該階段前面的狀態(tài),但是該階段前面的狀態(tài)是如何得來(lái)的與該階段無(wú)關(guān)。我們稱這樣的過(guò)程為多階段決策過(guò)程。

事實(shí)上,動(dòng)態(tài)規(guī)劃就是解決多段決策過(guò)程最優(yōu)問(wèn)題的一種方法

在使用動(dòng)態(tài)規(guī)劃法求解問(wèn)題時(shí),被求解的問(wèn)題應(yīng)滿足最優(yōu)性原則

一個(gè)最優(yōu)問(wèn)題的任何實(shí)例的最優(yōu)解是由該實(shí)例的子實(shí)例的最優(yōu)解組成的(子問(wèn)題最優(yōu),全局才能最優(yōu))

拿斐波那契數(shù)列來(lái)說(shuō)

  • 如果我們直接使用遞歸表達(dá)式求解的話回耗費(fèi)很大內(nèi)存且會(huì)被重復(fù)計(jì)算
  • 而如果我們正向計(jì)算,把每一次計(jì)算的結(jié)果保存起來(lái),則只需要進(jìn)行加法運(yùn)算,則大大地方便了計(jì)算

因此,對(duì)于交疊子問(wèn)題的求解,我們也可以使用這種方式:

對(duì)交疊子問(wèn)題的每個(gè)較小子問(wèn)題求解一次后記錄在表中,就可以從表中得到原始問(wèn)題的解

01背包問(wèn)題的動(dòng)態(tài)規(guī)劃求解

我們這里舉例說(shuō)明背包問(wèn)題的動(dòng)態(tài)規(guī)劃求解

背包容量為5,各種物品的重量及價(jià)值如下:

物品重量?jī)r(jià)值
1212
2110
3320
4215

正如前面我們所分析的,我們通過(guò)填表的方式利用動(dòng)態(tài)規(guī)劃的方式求解的話能夠大大地簡(jiǎn)化問(wèn)題的求解:

我們用V(i,j)V(i,j)V(i,j)表示將前i個(gè)物品放到容量為j的背包中時(shí)最優(yōu)解的物品總價(jià)值,則在裝入物品的時(shí)候我們有兩種情況:

  • 第i個(gè)物品不能被放入背包,則背包的價(jià)值為原先沒(méi)有裝入第i個(gè)物品時(shí)的價(jià)值:
    V(i,j)=V(i?1,j)V(i,j) = V(i - 1,j)V(i,j)=V(i?1,j)
  • 可將物品放入背包,應(yīng)對(duì)放入物品放入背包后的情況進(jìn)行評(píng)估,如果放入后背包的價(jià)值增加,則放入,否則不放入,價(jià)值為原來(lái)的沒(méi)有放入時(shí)的價(jià)值:
    V(i,j)=max{V(i?1,j),vi+V(i?1,j?wi)}V(i,j) = max\{ V(i - 1,j),{v_i} + V(i - 1,j - {w_i})\} V(i,j)=max{V(i?1,j),vi?+V(i?1,j?wi?)}
  • 即:

    我們對(duì)背包容量為0到5填表,得到表的情況如下:

    重量?jī)r(jià)值iii\ jjj012345
    0000000
    21210012121212
    110201012222222
    320301012223032
    215401015253037

    最終的最優(yōu)解為表的后一個(gè)元素37

    01背包問(wèn)題的動(dòng)態(tài)規(guī)劃求解-C++實(shí)現(xiàn)

    #include <iostream> using namespace std; int knapsack(int num,int capacity,int weight[],int value[]){//使用動(dòng)態(tài)規(guī)劃求解0-1背包問(wèn)題/*@parameters:@num:物品數(shù)量,整數(shù)類型@capacity:背包容量,整數(shù)類型@weight:各個(gè)物品的重量,數(shù)組類型@value:各個(gè)物品的價(jià)值,數(shù)組類型*/int space,sub_cap,total_value[num+1][capacity+1];for(int i=0;i<=num;i++)for(int j=0;j<=capacity;j++)total_value[i][j]=0;//初始化記憶表格for(sub_cap=1;sub_cap<=capacity;sub_cap++){for(space=1;space<=num;space++){if(sub_cap>=weight[space-1]){//判斷是否能不能裝下//能裝下,判斷裝了以后是不是背包的價(jià)值更大了total_value[space][sub_cap]=max(total_value[space-1][sub_cap],total_value[space-1][sub_cap-weight[space-1]]+value[space-1]);}else{//裝不下的話背包價(jià)值還是沒(méi)有裝之前的價(jià)值total_value[space][sub_cap]=total_value[space-1][sub_cap];}}}return total_value[num][capacity]; } int main(){int num=4,capacity=5,weight[]={2,1,3,2},value[]={12,10,20,15};cout<<knapsack(num,capacity,weight,value);return 0; }

    代碼的運(yùn)行結(jié)果為:

    37

    才疏學(xué)淺,難免有錯(cuò)誤和不當(dāng)之處,歡迎交流批評(píng)指正!
    同時(shí)有問(wèn)題的話歡迎留言或郵箱聯(lián)系(ljt_IT@163.com)。

    創(chuàng)作不易,覺(jué)得寫(xiě)得不錯(cuò)就微信掃碼獎(jiǎng)勵(lì)一下吧!

    總結(jié)

    以上是生活随笔為你收集整理的01背包问题的动态规划求解及其C++实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。