1. 程式人生 > >強行刷段位第十一天

強行刷段位第十一天

肚子痛。。。

又可以在部落格正文的開始絮絮叨叨了。

不喜歡在家裡學習,又不知道去哪好。

外面都沒有電誒,我的筆記本撐不了太久。

感冒好差不多了。

昨天在姥姥家擤鼻涕,一直擤一直擤,一直擤一直擤。。。有一瞬間我覺得我這輩子就要在擤鼻涕中度過了。

我就坐在床上擤擤擤,姥姥就在旁邊看著我呵呵呵的笑。

 

今天還是略有不適,但幾乎好了。

下午有時間去剪頭髮。

 

做題。


揹包型動態規劃第一題:

題目:

有一個箱子容量為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;	
 }