強行刷段位第十一天
肚子痛。。。
又可以在部落格正文的開始絮絮叨叨了。
不喜歡在家裡學習,又不知道去哪好。
外面都沒有電誒,我的筆記本撐不了太久。
感冒好差不多了。
昨天在姥姥家擤鼻涕,一直擤一直擤,一直擤一直擤。。。有一瞬間我覺得我這輩子就要在擤鼻涕中度過了。
我就坐在床上擤擤擤,姥姥就在旁邊看著我呵呵呵的笑。
今天還是略有不適,但幾乎好了。
下午有時間去剪頭髮。
做題。
揹包型動態規劃第一題:
題目:
有一個箱子容量為V(正整數,0<=V<=20000),同時有n個物品(0<n<=30),每個物品有一個體積(正整數)。
要求n個物品中,任取若干個裝入箱內,使箱子的剩餘空間為最小。
輸入描述:
一個整數v,表示箱子容量
一個整數n,表示有n個物品
接下來n個整數,分別表示這n 個物品的各自體積
輸出描述:
一個整數,表示箱子剩餘空間。
樣例輸入:
24
6
8
3
12
7
9
7
樣例輸出:
0
我的答案:
今天是頭一次接觸動態規劃問題,就先學習了一波。
揹包問題是動態規劃裡最基礎的入門問題了。
有一個入門,叫做:通過金礦模型介紹動態規劃。可以保證看過就懂,迅速瞭解動態規劃是什麼,地址:http://www.cnblogs.com/sdjl/articles/1274312.html
看完之後心裡就已經有了比較清晰的概念。
可是怎麼實現是一個問題。我嘗試了用遞迴,emmm,並沒有想象的順利。
然後又看了一波其他的教程。
哦,原來用二維陣列。然後就很清晰啦。
對於我自己而言,說白了就是一個填表的過程,這個表的填寫過程模擬了動態規劃的過程。
解決此類問題,首先要抓住動態轉移方程。
本題的動態轉移方程為:f[i][j]=max(f[i-1][j],f[i-1][j-arr[i]]+arr[i])
其中,f[i][j]表示將前i個物品裝入容量為j的箱子,獲得的最大體積
然後按照這個規律進行填表。
過程中注意三點:
1.如果迴圈從0開始,會出現第0行無法在迴圈中填入這種情況,需要提前賦值。
所以最好從第一行第一列開始填。
我寫的時候把這個二維陣列寫成了全域性變數。全域性變數的初值統一為0,這樣在進行第一行賦值時可以運用第0行的初值而無需單獨賦值。
2.要注意,輸入的arr[]陣列也要從1開始
3.j<arr[i],即容量小於當前要裝入的第i個物品,那麼f[i][j]=f[i-1][j],即不裝這個。
如此看來,輸入的資料v和n,實際上是控制填表的範圍,而物品的大小和箱子容積控制著填表的內容。
從而最終獲得想要的表項。
程式碼如下:
#include <iostream>
using namespace std;
int arr[31];
int f[31][20001]; //表示前i個物品,裝入容量為j的箱子,最大的體積是多少
int main()
{
int v=0,n=0,i=0,j=0,m=0;
cin>>v;
cin>>n;
for(i=1;i<=n;i++) cin>>arr[i];
for(i=1;i<=n;i++)
for(j=1;j<=v;j++)
{
if(j<arr[i]) f[i][j]=f[i-1][j]; //當前空間無法裝下第i個物品,則不裝
else f[i][j]=max(f[i-1][j],f[i-1][j-arr[i]]+arr[i]); //能裝下,再討論裝不裝
}
cout<<v-f[n][v];
return 0;
}