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

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

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

动态规划之买瓜子—C说算法系列

發(fā)布時(shí)間:2024/3/12 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态规划之买瓜子—C说算法系列 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

熟能生巧,大多數(shù)的解題步驟或者思路都可通過(guò)訓(xùn)練獲得。將事情重復(fù)做,即使剛開(kāi)始你感覺(jué)素手無(wú)錯(cuò),一臉茫然,但是通過(guò)重復(fù)訓(xùn)練最終也能夠游刃有余


題目來(lái)源:第十二屆藍(lán)橋杯青少年國(guó)賽C++中級(jí)組-編程題4

這是一道DP(動(dòng)態(tài)規(guī)劃)的題目,大家都知道,DP算法的效率極高,但是較難理解。在很多算法的題解中對(duì) DP在該題中的應(yīng)用思路? 只簡(jiǎn)單提了幾句。我們來(lái)看一道題,或許題解過(guò)程能讓你對(duì)DP的理解更加深入一些。

題目?jī)?nèi)容:

校慶,采購(gòu)瓜子。資金N(1<=N<=1000)M(1<=M<=30)種瓜子。問(wèn)最多能采購(gòu)多少千克的瓜子?比如N=80元,M=2種。第1種,每袋18元10千克;第2種,每袋30元20千克。

輸入樣例:

80 2

18 10

30 20

輸出樣例

50

提示:18+30+30=78元 10+20+20=50千克


分析:

這是完全背包問(wèn)題,是一道模板題,是必須要掌握的(背代碼也要背下來(lái))那什么是完全背包問(wèn)題呢?

完全背包問(wèn)題:一般是指,有N件物品和一個(gè)能背重量為W的背包,第i件物品的重量為weight[i],價(jià)格為value[i]。每件物品有無(wú)限個(gè)(也就是可以放入背包多次),求怎樣可以使背包物品價(jià)值總量最大

本道題我們完全可以套模板。資金N元(按照完全背包問(wèn)題的解釋,我們可以把N看成W),即有M種瓜子,有資金N元,求怎樣可以使買(mǎi)的瓜子重量最多?

動(dòng)態(tài)規(guī)劃算法最重要的兩點(diǎn)是:

1、確定dp數(shù)組和下標(biāo)的含義? ? ? ? 2、確定遞推公式(選或者不選物品)

本題中的dp數(shù)組我們可以這樣定義:int dp[50][1010];?

dp[i][w]代表 - 前i個(gè)物品,在價(jià)值為w的情況下,最大的重量是dp[i][w]

因?yàn)镸<=30,物品的數(shù)量不會(huì)大于30,所以dp的第一個(gè)維度,我們?cè)O(shè)置一個(gè)大于30的長(zhǎng)度即可。資金W<=1000,dp的第二個(gè)維度代表資金,資金<=1000,所以第二個(gè)維度我們?cè)O(shè)置一個(gè)大于1000的長(zhǎng)度即可。


該題中涉及到的數(shù)據(jù)結(jié)構(gòu)有:

數(shù)據(jù)的輸入

輸入資金和瓜子種數(shù)

?

數(shù)據(jù)的處理

此步是最核心最關(guān)鍵的,我們定義了dp[i][w]數(shù)組,該數(shù)組的含義代表前i個(gè)物品,在價(jià)格為w的情況下,最大的重量是dp[i][w],對(duì)于本題的例子當(dāng)N=80,M=2的情況下,最多能買(mǎi)50kg的瓜子。即求出dp[2][80]的值。

在dp中,要求出dp[i][j]的值,需要通過(guò)遞推計(jì)算而來(lái)。

注意:要認(rèn)真區(qū)別此處各種符號(hào)表示的含義。

對(duì)于每一種瓜子,都有選與不選兩種選擇。dp數(shù)組的初始化,當(dāng)i=0或者w=0的情況下,dp[i][w]均為0,因?yàn)閐p[0][w]代表前0件商品,在價(jià)格為w的情況下,最大的重量,既然沒(méi)有商品,那么最大的重量肯定為0,dp[i][0]代表前i件商品,在資金為0下,最大的重量,既然沒(méi)有資金,那么最大的重量肯定為0.

以資金=80,種類(lèi)=2為例,有:

dp[0][0],dp[0][1],dp[0][2],dp[0][3],dp[0][4]……dp[0][80]的值均為0.

dp[0][0],dp[1][0],dp[2][0],dp[3][0],dp[4][0]……dp[50][0]的值均為0.

可通過(guò)嵌套for循環(huán)進(jìn)行遞推,利用for循環(huán)求出dp[i][w]

在當(dāng)前資金j不夠買(mǎi)第i種瓜子的情況下,dp[i][j]的值等于dp[i-1][j]的值,dp[i-1][j]代表前i-1種瓜子,在價(jià)格為j下,最大的重量為dp[i-1][j].

比如對(duì)于dp[1][16],在前1種瓜子下,當(dāng)前資金是16元,但是根據(jù)題目意思,第1種瓜子的價(jià)格為18,所以dp[1][16]=dp[0]=16]=0千克,無(wú)法買(mǎi)瓜子,所以最大重量為0

再比如對(duì)于dp[1][18],在前1種瓜子下,當(dāng)前資金是18元,第1種瓜子的價(jià)格剛好為18元,資金足夠,根據(jù)代碼dp[1][18]=max(dp[0][18],dp[1][0]+10)=10千克,所以最大重量為10千克

再比如對(duì)于dp[2][19],,在前2種瓜子下,當(dāng)前資金是19元,當(dāng)前第2種瓜子的價(jià)格為30元,資金不夠,因此dp[i][j]=dp[i-1][j]=dp[2][19]=dp[1][19]=10千克

對(duì)于每一種瓜子,只有買(mǎi)和不買(mǎi)兩種選擇,對(duì)于前i種瓜子,在現(xiàn)有資金為j下,如果資金足夠,我們可以買(mǎi),也可以不買(mǎi),那到底買(mǎi)不買(mǎi)呢?

買(mǎi)不買(mǎi)取決于:如果不買(mǎi)的重量比買(mǎi)了的重量更大,就不買(mǎi),如果買(mǎi)了的重量比不買(mǎi)的重量更大,就買(mǎi)。本題例子的輸入,不好解釋dp[i][j]=max(dp[i-1][j],dp[i][j-wt[i]]+v[i]);這一現(xiàn)象,我們可以更改一下輸入,即?

80 2

30 20

18 10

比如要求:dp[2][30]=max(dp[1][30],dp[2][30-18]+v[2])=max(20,10)=20,前2種瓜子,當(dāng)資金為30,最大的重量為20.因?yàn)楫?dāng)資金30時(shí),如果不選擇買(mǎi)18元的瓜子,就有20千克,如果選擇買(mǎi)18元的瓜子,最終的重量就只有10千克

注意:這里是一種瓜子可以被選擇多次。

數(shù)據(jù)的輸出

n代表瓜子的數(shù)量,w代表錢(qián)的數(shù)量,對(duì)于本道題而言就是dp[2][80]=50?

遞推表格(演示樣例,當(dāng)資金=80元,瓜子種類(lèi)數(shù)為2種時(shí),最大的重量):

?

代碼實(shí)現(xiàn):

#include<bits/stdc++.h> using namespace std;int dp[50][1010]; //表示,前i個(gè)物品,在價(jià)值w的情況下,最大的重量是dp[i][w] int wt[1010],v[50]; //wt是價(jià)格,v是重量 int n,w; int main() {cin>>w>>n; for(int i=1;i<=n;i++)cin>>wt[i]>>v[i]; //wt[i]代表第i種瓜子多少錢(qián) v[i]代表第i種瓜子多少千克 for(int i=1;i<=n;i++) //遍歷n種瓜子,每種要么選,要么不選 {for(int j=1;j<=w;j++) //j是價(jià)格 {if(j>=wt[i]) //wt是價(jià)格 {if(dp[i-1][j]>dp[i][j-wt[i]]+v[i]){dp[i][j]=dp[i-1][j];}else{dp[i][j]=dp[i][j-wt[i]]+v[i];}}else{dp[i][j]=dp[i-1][j]; }}}cout<<dp[n][w]<<endl;return 0; }

總結(jié):

動(dòng)態(tài)規(guī)劃的題目還是要多做,做著做著自然會(huì)有靈感,如果你一開(kāi)始覺(jué)得很難,就不去動(dòng)手敲代碼,那你永遠(yuǎn)也學(xué)不會(huì)動(dòng)態(tài)規(guī)劃,不僅動(dòng)態(tài)規(guī)劃,其它題目也是如此。最后送給大家一句話(huà)學(xué)如逆水行舟不進(jìn)則退。

大家可以進(jìn)微信群討論數(shù)據(jù)結(jié)構(gòu)與算法,也有資源分享給大家:微信號(hào)Q1313135,非誠(chéng)勿擾.

總結(jié)

以上是生活随笔為你收集整理的动态规划之买瓜子—C说算法系列的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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