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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【动态规划】三种基本背包问题

發(fā)布時間:2025/3/15 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【动态规划】三种基本背包问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

動態(tài)規(guī)劃?是對解最優(yōu)化問題的一種途徑 它往往是針對一種最優(yōu)化問題 根據(jù)問題的不同性質(zhì) 確定不同的設(shè)計方法?
因為這篇文章我想說點關(guān)于背包問題的事情 所以不再過多介紹動態(tài)規(guī)劃?
背包問題?是動態(tài)規(guī)劃中的一個經(jīng)典題型 在聯(lián)賽中也經(jīng)常出現(xiàn) 其基本問題主要分為01 完全 多重 三種?
下面就通過程序與例題分別來說一下三種基本問題

01背包

有n件物品和容量為m的背包 給出i件物品的重量以及價值 求解讓裝入背包的物品重量不超過背包容量 且價值最大?
特點?這是最簡單的背包問題 特點是每個物品只有一件供你選擇放還是不放

對于這個問題一般有兩種解法 下面分別來介紹一下

① 二維解法?
設(shè)f[i][j]表示前i件物品 總重量不超過j的最大價值 可得出狀態(tài)轉(zhuǎn)移方程?
f[i][j]=max{f[i-1][j-a[i]]+b[i],f[i-1][j]}?

或許到這里大家對這個方程還不是那么熟悉,我們便通過一個實例來走一遍:

物品件數(shù)n=4,背包容量m=8

物品編號1234
w(體積)
v(價值)

初始化:?
?
總表:?

現(xiàn)在挑幾個典型的說一下這個表是怎么更新的:?
點(i=2,j=3):這時有兩個物品可以放入,背包容量為3,此時我們面臨一個抉擇,放還是不放第二件物品,我們看一下,上一狀態(tài),也就是只有一件物品或者說我們不放這件物品時的最大價值(i=1,j=3)為3,再看一下如果我們放這件物品的最大價值,(此時空間明顯不足以同時放入這兩件物品,我們?nèi)绻胚@件物品總得給它留出足夠的空間吧,所以我們計算一下當給他留出足夠空間時,空間還剩多少,此時背包的最大價值是多少)(i=1,j=3-3=0)為0(也就是說此時我如果想放入第二件物品的話,就得把第一件物品拿出來,拿出來后背包價值是0),再把第二件物品放進去,此時背包價值為4,我們比較一下這兩個狀態(tài),如果不放第二件物品背包價值為3,放第二件物品背包價值為4,我們當然選擇翻入第二件物品。?
如果這個點還是不太明白我們再試一個點,算法是一樣的?
點(i=3,j=7):這時有三個物品可以放入,背包容量為7,我們面臨一個抉擇,放還是不放第三個物品,

這個地方我一開始有點迷,點(i=3,j=6)的時候我已經(jīng)把第三個物品放進去了,那還這個點我還 看放不放他干啥,這時候不還得判斷是不是得扔哪個物品嗎?是不是有點傻?這時候我們的上一狀 態(tài)是背包容量為j時,有兩個物品可放的最大價值,可以說i相等時,每個點都是獨立的,互不相 關(guān),所以此時我們比較的是(i=2,j=7)這個點,要看的是,當有二個物品可以放入,背包容量為7 時再放入第三個物品能不能使背包的價值更大。

我們看一下,上一狀態(tài),也就是只有一件物品或者說我們不放這件物品時的最大價值(i=2,j=7)為7,再看一下如果我們放這件物品的最大價值,(此時空間明顯不足以同時放入這兩件物品,我們?nèi)绻胚@件物品總得給它留出足夠的空間吧,所以我們計算一下當給他留出足夠空間時,空間還剩多少,此時背包的最大價值是多少)(i=2,j=7-4=3)為4((重點理解!!!)也就是說要想放入第三個物品得給給他讓出v[3]=4的容量,此時背包容量還剩3,我們可以知道,背包容量為3時背包最大價值為(i=2,j=3)=4),再把第三件物品放進去,此時背包價值為4+5=9,我們比較一下這兩個狀態(tài),如果不放第三件物品背包價值為7,放第二件物品背包價值為9,我們當然選擇翻入第三件物品。

代碼如下

#include<iostream> using namespace std; int main() {int m,n;cin>>n>>m;int a[50001],b[50001];int f[5001][5001];for(int i=1;i<=n;i++)cin>>a[i]>>b[i];for(int i=1;i<=n;i++)for(int j=m;j>0;j--){if(a[i]<=j)f[i][j]=max(f[i-1][j],f[i-1][j-a[i]]+b[i]);else f[i][j]=f[i-1][j];}cout<<f[n][m]<<endl; //最優(yōu)解//COYG }

雖然“原理”沒有錯 但是f數(shù)組開的太大 (一般應(yīng)該5000就頂頭了)?
在一些情況下 題目的數(shù)據(jù)會很大 因此f數(shù)組不開到一定程度是沒有辦法ac的 那么該怎么辦呢 于是

②一維解法?
設(shè)f[j]表示重量不超過j公斤的最大價值 可得出狀態(tài)轉(zhuǎn)移方程?

fj=maxj{fj,f[j?a[i]]+b[i]}fj=maxj{fj,f[j?a[i]]+b[i]}


代碼如下

?

#include<iostream> using namespace std; int main() {int n,m;cin>>n>>m;int a[50001],b[50001]; for(int i=1;i<=n;i++)cin>>a[i]>>b[i];int f[50001]={0};for(int i=1;i<=n;i++){ for(int j=m;j>=a[i];j--)if(f[j-a[i]]+b[i]>f[j])f[j]=f[j-a[i]]+b[i]; }cout<<f[m]<<endl; //最優(yōu)解//COYG }

這樣用一維數(shù)組代替二維數(shù)組就解決了很多問題 所以用一維數(shù)組解決01背包是很重要的

01背包的例題有:[USACO07DEC]手鏈Charm Bracelet(洛谷搜索 P2871) 采藥(洛谷搜索 P1048) [Noip普及組2001]裝箱問題(洛谷搜索 P1049)

完全背包

有n件物品和容量為m的背包 給出i件物品的重量以及價值 求解讓裝入背包的物品重量不超過背包容量 且價值最大?
特點?題干看似與01一樣 但它的特點是每個物品可以無限選用

其實這個題也可以寫二維和一維兩種 但之前已經(jīng)說過了二維的有一定局限 所以在此之介紹一維?
一維?
設(shè)f[j]表示重量不超過j公斤的最大價值 可得出狀態(tài)轉(zhuǎn)移方程?

fj=maxj{fj,f[j?a[i]]+b[i]}fj=maxj{fj,f[j?a[i]]+b[i]}


代碼如下

?

#include<iostream> using namespace std; int main() {int n,m;cin>>n>>m;int a[50001],b[50001];int f[50001]={0};for(int i=1;i<=n;i++){cin>>a[i]>>b[i];}for(int i=1;i<=n;i++)for(int j=a[i];j<=m;j++){if(f[j-a[i]]+b[i]>f[j])f[j]=f[j-a[i]]+b[i];}cout<<f[m]<<endl;//最優(yōu)解//COYG }

大家有沒有感覺代碼很熟悉?每錯 一維完全背包的代碼與一維01背包的代碼只在循環(huán)上有些差別 而且狀態(tài)轉(zhuǎn)移方程也一樣

例題可以百度搜索收益(也叫投資)?
算了好人做到底我還是ctrl+v一下題目吧?
【題目描述】收益 (POJ 2063)?
“建太空梯進入太空要1兆億?”魔法學(xué)院的院長瞪大了眼睛。?
“這只是基礎(chǔ)設(shè)施的費用,后期還要……”墨老師掰著手指算。?
“哎呀,現(xiàn)在地主也很窮啊,學(xué)院的錢批下來就這么多,你想辦法用這筆錢在債券市場上獲得最大收益吧。”院長皺著眉頭。?
簡單來說,就是你有一筆錢,你要將這筆錢去投資債券,現(xiàn)在有d種債券,每種債券都有一個價值和年收益,債券的價值是1000的倍數(shù),問你如何投資在n年后的獲得最大收益。?
【輸入格式】?
第一個為一個整數(shù)M,表示有M組數(shù)據(jù)。?
每組數(shù)據(jù)第一行有兩個整數(shù),表示初始資金(不超過50000)和年數(shù)n。?
每組數(shù)據(jù)第二行為一個整數(shù)d(1 ≤ d≤10),表示債券種類。?
隨后d行每行有兩個整數(shù),表示該債券的價值和年收益。年收益不會超過債券價值的10%。?
所有數(shù)據(jù)不超過整型取值范圍。?
【輸出格式】?
每組數(shù)據(jù),輸出n年后獲得的最大收益。?
【輸入樣例】?
1?
10000 4?
2?
4000 400?
3000 250?
【輸出樣例】?
14050

貼一下我這個題的代碼

#include<iostream> #include<cstring> using namespace std; int main() {int m,y,n,d,ans=0,a[100001],b[100001];int f[100001]={0}; cin>>m;while(m--){cin>>y>>n;cin>>d;for(int i=1;i<=d;i++){cin>>a[i]>>b[i];}for(int o=1;o<=n;o++){for(int i=1;i<=d;i++)for(int j=a[i];j<=y;j++){f[j]=max(f[j-a[i]]+b[i],f[j]);}y+=f[y]; //每次都要累計memset(f,0,sizeof(f));}cout<<y<<endl;}return 0; } //小蒟蒻代碼丑 //COYG

多重背包

有n件物品和容量為m的背包 給出i件物品的重量以及價值 還有數(shù)量 求解讓裝入背包的物品重量不超過背包容量 且價值最大?
特點?它與完全背包有類似點 特點是每個物品都有了一定的數(shù)量

狀態(tài)轉(zhuǎn)移方程為:?

f[j]=max{f[j],f[j?k?a[i]]+k?b[i]}f[j]=max{f[j],f[j?k?a[i]]+k?b[i]}


【輸入樣例】?
8 2?
2 100 4?
4 100 2?
【輸出樣例】?
400

?

代碼如下

#include<iostream>using namespace std; int main() {int m,n;cin>>m>>n;int a[10001],b[10001],c[10001];for(int i=1;i<=n;i++){cin>>a[i]>>b[i]>>c[i];}int f[10001];for(int i=1;i<=n;i++)for(int j=m;j>=0;j--)for(int k=0;k<=c[i];k++){if(j-k*a[i]<0)break;f[j]=max(f[j],f[j-k*a[i]]+k*b[i]);}cout<<f[m]<<endl;//最優(yōu)解 }

總結(jié)

以上是生活随笔為你收集整理的【动态规划】三种基本背包问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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