【动态规划入门】装箱问题

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数组的部分变化

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