Description
有一個箱子容量為V(正整數,0<=V<=20000),同時有n個物品(0<=n<=30),每個物品有一個體積(正整數)。
要求n個物品中,任取若干個裝入箱內,使箱子的剩余空間為最小。
Input
每個測試文件只包含一組測試數據,每組輸入的第一行為一個整數V(0<=V<=20000),表示箱子的容量。
第二行輸入一個整數n(0<=n<=30),表示有n個物品。
接下來n行,每行輸入一個正整數,表示每個物品的體積。
Output
對於每組輸入數據,輸出一個整數,表示箱子剩余的最小空間。
Sample Input 1
24
6
8
3
12
7
9
7
Sample Output 1
0
Sample Input 2
90
12
3
7
4
5
13
2
8
4
7
6
5
7
12
3
7
4
5
13
2
8
4
7
6
5
7
Sample Output 2
19
解題思路:利用動態規划
我自己一開始的錯誤思想是用貪心算法,覺得先把最大的存進去,剩余的體積就是最小。題目提供的樣例都過了,但是提交的時候卻在某個樣例錯了。后來想了想才知道我這種想法有錯誤之處,先貼出我自己的錯誤代碼
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 5 int V,n; 6 int a[40]; 7 int sum = 0; 8 int main() 9 { 10 cin>>V; 11 cin>>n; 12 for(int i = 0 ;i < n ;i++) 13 { 14 cin>>a[i]; 15 sum += a[i]; 16 } 17 if(sum<=V) cout<<V-sum; 18 else 19 if(sum>V) 20 { 21 sort(a,a+n); 22 for(int i = n-1 ;i>=0;i--) 23 { 24 V -= a[i]; 25 if(V<0) 26 { 27 V += a[i]; 28 continue; 29 } 30 } 31 cout<<V; 32 } 33 return 0; 34 35 }
但是這種的話,后來想了一下,對於該數據正確答案是輸出0,但是上述代碼輸出了1;因為代碼先把99存進去了;
100
4
99 98 2 2
后來看了別人的博客,是利用動態規划
思路:
對於每一個物體,都有兩種選擇-放入或者不放入,所以外層循環可對每個物品進行遍歷,而每選擇一個物品,定會對大於該物品體積的dp數組元素產生影響,從而還需要一個內層數組對大於該物品體積的dp數組元素進行遍歷更新。更新方法為:dp[i] = max{ dp[i] , dp[i - vi]+vi },其中vi為當前物品的體積,max中的dp[i]表示不放入該物體時的解, dp[i - vi]+vi表示放入該物體時的解(i-vi表示給即將放入的物品留出合適的體積,如之前的例子,dp[i-vi]並不一定等於dp[i] - vi),取最大值,即為最優解。需要注意的是,需要先將dp數組中的每一個元素初始化為0。
對於如何運用 dp[i] = max{ dp[i] , dp[i - vi]+vi },下面舉個例子詳細說明一下過程。
原文:https://blog.csdn.net/elma_tww/article/details/86507716
原文:https://blog.csdn.net/elma_tww/article/details/86507716


繼續進行下去,直到遍歷完所有物品。
主要是思想,代碼其實挺簡單的,代碼如下:
1 #include<iostream> 2 #include<cmath> 3 #include<string.h> 4 using namespace std; 5 6 7 int V,n; 8 int a[40]; 9 int main() 10 { 11 cin>>V; 12 cin>>n; 13 int dp[V+1]; 14 memset(dp,0,sizeof(dp)); 15 for(int i = 0 ;i < n;i++) 16 { 17 cin>>a[i]; 18 for(int j = V;j >= a[i];j--) 19 { 20 dp[j] = max(dp[j],dp[j-a[i]]+a[i]); 21 } 22 } 23 cout<<V-dp[V]; 24 return 0; 25 }