[NOIP2001 普及组] 装箱问题
题目描述
有一个箱子容量为 ,同时有 个物品,每个物品有一个体积。
现在从 个物品中,任取若干个装入箱内(也可以不取),使箱子的剩余空间最小。输出这个最小值。
输入格式
第一行共一个整数 ,表示箱子容量。
第二行共一个整数 ,表示物品总数。
接下来 行,每行有一个正整数,表示第 个物品的体积。
输出格式
- 共一行一个整数,表示箱子最小剩余空间。
样例 #1
样例输入 #1
24
6
8
3
12
7
9
7
样例输出 #1
0
提示
对于 数据,满足 ,。
【题目来源】
NOIP 2001 普及组第四题
思路
首先从输入中读取箱子的总容量v和物品的数量n,然后读取每个物品的体积并存储在数组a中。
一维数组 dp[j] 用于存储当箱子的容量为j时,能够装入的最大体积。也就是说,对于一个给定的j,dp[j]表示的是在不超过j容量限制的前提下,能够装入的物品的最大总体积。
状态转移方程:
dp[j] = max(dp[j], dp[j - a[i]] + a[i])
更新当前容量j下,能够装入的最大体积。
这个操作是在比较两种情况:一种是不放入当前物品a[i]时的最大体积dp[j],另一种是放入当前物品a[i]后的总体积dp[j - a[i]] + a[i]。取这两种情况的最大值,就得到了新的dp[j],也就是在考虑了当前物品a[i]之后,能够装入的最大体积。
动态规划的过程在第二个for循环中。这个循环遍历每个物品,然后对于每个物品,从箱子的总容量开始递减,直到当前物品的体积。这个循环的目的是尝试把当前物品放入箱子,并更新箱子的当前容量。如果把当前物品放入箱子后,箱子的容量能够增大(即更接近满载),那么就更新箱子的当前容量。这个动态规划的过程实际上是在尝试所有可能的组合,找到能够最大化箱子容量的物品组合。
最后,输出v - dp[v],这是箱子未被装满的体积,也就是箱子的剩余空间。
AC代码
#include <algorithm>
#include <iostream>
#define AUTHOR "HEX9CF"
using namespace std;
const int N = 1e7 + 7;
int v, n;
int a[N];
int dp[N];
int main() {
cin >> v >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int i = 1; i <= n; i++) {
for (int j = v; j >= a[i]; j--) {
dp[j] = max(dp[j], dp[j - a[i]] + a[i]);
}
}
cout << v - dp[v] << endl;
return 0;
}