1014 装箱问题
2001年NOIP全国联赛普及组
时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold
题目描述 Description
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
输入描述 Input Description
一个整数v,表示箱子容量一个整数n,表示有n个物品
接下来n个整数,分别表示这n 个物品的各自体积
输出描述 Output Description
一个整数,表示箱子剩余空间。样例输入 Sample Input
246
8
3
12
7
9
7
样例输出 Sample Output
0
一、分类
动态规划,01背包问题
二、思路
1.状态转移方程
设arr[i][j] 为:考虑前i个物品时,背包容量为v个体积时,最少的剩余空间。
考虑第i个物品,若体积大于背包,则放不进箱子。若体积小于背包,则产生两种情况,1.放 2.不放,比较两种状态取最小值。
设j为体积,i 为考虑前i个箱子
不放时,最小剩余容量为arr[i-1][j]; 放时,最小剩余容量为arr[i-1][j-co[i]],,co[i]为第i个箱子的体积。
arr[i][j]=MIN(arr[i-1][j],arr[i-1][j-co[i]]); ,co[i]<=j // min(不放,放),第i个箱子能够放入
arr[i][j]=arr[i-1][j]; ,co[i]>j //j体积时 第i个箱子不能放入,即剩余体积等于前i-1个箱子j体积时的最优解
2.初始化
考虑前0个物品时,最少的剩余空间 = 背包容量 。即arr[0][i]=i, 0<=i<=v
3.答案
输出结果应为arr[n][v],即考虑全体积和所有箱子时的最优解
三、AC代码
#include<stdio.h>
#define MIN(a,b) ((a)>(b)?(b):(a))
int arr[40][30000]={0};
int co[40];
int main()
{ //经典dp,01背包
int v;
int n;
scanf("%d %d",&v,&n);
int i;
for(i=1;i<=n;i++)
{
scanf("%d",co+i);
}
int j;
for(i=1;i<=v;i++)
{
arr[0][i]=i;
}
for(i=1;i<=n;i++)
{
for(j=1;j<=v;j++)
{
if(j>=co[i])
{
arr[i][j]=MIN(arr[i-1][j],arr[i-1][j-co[i]]);
}
else
arr[i][j]=arr[i-1][j];
}
}
printf("%d",arr[n][v]);
}