【動態規劃入門】裝箱問題

1014 裝箱問題
2001年NOIP全國聯賽普及組
時間限制: 1 s 空間限制: 128000 KB 題目等級 : 黃金 Gold 題解
題目描述 Description
有一個箱子容量爲V(正整數,0<=V<=20000),同時有n個物品(0<n<=30),每個物品有一個體積(正整數)。
要求n個物品中,任取若干個裝入箱內,使箱子的剩餘空間爲最小。
輸入描述 Input Description

一個整數n,表示有n個物品

接下來n個整數,分別表示這n 個物品的各自體積

輸出描述 Output Description

一個整數,表示箱子剩餘空間。

樣例輸入 Sample Input

24

6

8

3

12

7

9

7

樣例輸出 Sample Output

0
鏈接:http://codevs.cn/problem/1014/
動態規劃入門相關資料:http://www.hawstein.com/posts/dp-novice-to-advanced.html

解題思路:
動態規劃的核心思想就是將問題劃分爲n個存在共同子問題的子問題,並將這些子問題的結果計算並存儲起來,一般爲數組。
本題使用一維數組dp來記錄在當前空間下的最大填充體積,dp[j] ->在體積爲j的情況下最大填充爲dp[j];由於在對一個物體來說,它有兩種狀態,放入箱子dp[i-num[j]]+num[j],或者不放入dp[j],我們需要的是這兩者中的較大的一個,即:dp[j] = max(dp[j],dp[i-num[j]]+num[j]);
對於dp[i-num[j]]的解釋可以參考動態規劃:從新手到專家 中狀態相關介紹
代碼:

 #include <iostream>
 #include <cmath>
 #include <algorithm>
 
 using namespace std;
 
 int main()
 {
 	int n,m;
 	cin >> n >> m;
 	int num[40] = {0};//記錄每個物體的體積,要求30就可以,習慣開大點
 	int dp[20005] = {0};//記錄在j下最大體積V,要求是20000
 	for(int i = 0; i < m; i++)//輸入
 		cin >> num[i];
 	for(int i = 0; i < m;i++)//將給出的物體放入箱子,防止重複計算
 	{
 		for(int j = n; j >= num[i]; j--)//判斷物體是否放入箱子
 		{
			 	dp[j] = max(dp[j],dp[j-num[i]]+num[i]);
 		}
 	}
 	cout < <n - dp[n] <<endl;
 	return 0;
 } 

這道題中比較技巧的就是那兩層for循環,外面那一層的目的是將給出的物體體積一個一個去進行比較,比如第一個物體體積是4,從n到4,所有的dp[j]都會變成4,得到了當填入4時所有子問題(在容量爲j時最大填充量)的值
當測試數據爲10 3 4 5 8 dp數組的部分變化

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章