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時最大填充量)的值