算法训练 装箱问题
时间限制:1.0s 内存限制:256.0MB
问题描述
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入格式
第一行为一个整数,表示箱子容量;
第二行为一个整数,表示有n个物品;
接下来n行,每行一个整数表示这n个物品的各自体积。
第二行为一个整数,表示有n个物品;
接下来n行,每行一个整数表示这n个物品的各自体积。
输出格式
一个整数,表示箱子剩余空间。
样例输入
24
6
8
3
12
7
9
7
样例输入
24
6
8
3
12
7
9
7
样例输出
0
题目解析:
本题所涉及到的算法为动态规划。
利用 dp[n][v]来保存 n 件物品装入容量为 v 的背包所的得到的最大体积。对于每一件物品,都需要考虑装还是不装:
- 如果所给物品的体积大于背包的容量,那么不装,即当前装入的最大体积为上一个物品装入时得到的最大体积:dp[i][j] = d[i-1][j];
- 如果所给物品的体积小于或等于背包的容量,那么考虑装入或不装:(1)如果装入后得到的最大体积小于或等于之前的最大体积,那么不装;(2)如果大于之前的最大体积,那么装入。即,将之前装入得到的最大体积和此物件装入得到的最大体积中的最大值存入 dp[i][j]:dp[i][j] = max( dp[i-1][j], dp[i-1][j-t]+t)。
示例代码:
1 #include<iostream> 2 using namespace std; 3 4 int dp[31][20001]; //dp[i][j]表示 i 件物品中选取某些物品装入容量为 j 的背包所得到的最大体积 5 6 int main() 7 { 8 int v, n; 9 cin >> v >> n; 10 11 int t; 12 for(int i = 1; i <= n; i++) 13 { 14 cin >> t; 15 for(int j = 1; j <= v; j++) 16 { 17 if (j >= t) //如果装入,那么计算其得到的最大体积 18 { 19 dp[i][j] = max(dp[i-1][j], dp[i-1][j-t] + t); 20 } 21 else //如果不装,最大体积为前一个物品装入后的最大体积 22 { 23 dp[i][j] = dp[i-1][j]; 24 } 25 } 26 } 27 28 cout << (v - dp[n][v]); //输出剩余体积(剩余体积 = 总容量 - n 件物品装入容量为 v 的背包所得到的最大体积) 29 30 return 0; 31 }