装箱问题
题目描述
有一个箱子容量为
V,同时有
n 个物品,每个物品有一个体积。
现在从
n 个物品中,任取若干个装入箱内(也可以不取),使箱子的剩余空间最小。输出这个最小值。
输入格式
第一行共一个整数
V,表示箱子容量。
第二行共一个整数
n,表示物品总数。
接下来
n 行,每行有一个正整数,表示第
i 个物品的体积。
对于每一个物体,都有两种状态:装 与不装
那么,对于任意重量m的最大价值 f (m) = max ( f ( m - w[i] ) + w[i], f (m) )(w为重量(即价值))
其中,f ( m - w[i] ) 指在装了物品i后,箱子的剩余容量能装的最大重量
f ( m - w[i] ) + w[i] 指在在装了物品i后,箱子能装的最大重量
24
6
8
3
12
7
9
7
给了以上例子
那我们如果能计算出容量为1的最大值,为2的最大值,为3的最大值如此依次递归,用 f (m) = max ( f ( m - w[i] ) + w[i], f (m) ),循环每个物品,来计算容量为1,2,3,4所能装的最大物品
``` int main(){
int v,a[31],V[20001];
int n;
scanf("%d",&v);
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(int i=0;i<=v;i++)
{
V[i]=0;
}
for(int i=0;i<n;i++)
{
for(int j=1;j<=v;j++)
{ if(j>a[i]){
if(V[j-a[i]]+a[i]>V[j])
{
V[j]=V[j-a[i]]+a[i];
}
}
}
}
printf("%d",v-V[v]);
return 0;
}
```
将所有容量初始为0;
第一个循环历变所有的容量从0到v(应为我们要从小的推到大的,比如我们知道v[3]最多存3,有个物品体积为a[0]=4(a数组存放物品体积a[0]第一个物品),v[7-a【0】]+a【0】=v[3]+a【0】>v[7],得出v[7]最多存7;
第二个循环历变所有物品
如v[8],就会依次与所有的物品比较,最开始8>(第一个物品)a[0]=6,在比较v[2]+a[0](6)于v[8]的大小,在比较第二个物品,依次循环;
将大的数付给v[8],这样依次进行下去,最后得出v[8]的最大值;
但我们发现循环到v[6],物品为大小为3时,v[6]=v[6-3]+3=v【3】+3;物品四体积为3的放了两次,
这无疑是大错特错;
递推那我们如何改变;
``` #include<stdio.h>
int main(){
int v,a[31],V[20001];
int n;
scanf("%d",&v);
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(int i=0;i<=v;i++)
{
V[i]=0;
}
for(int i=0;i<n;i++)
{
for(int j=v;j>=a[i];j--)
{
if(V[j-a[i]]+a[i]>V[j])
{
V[j]=V[j-a[i]]+a[i];
}
}
}
printf("%d",v-V[v]);
return 0;
}
```
那为什么我们从24开始就可以得出正确答案,为什么不从1开始,不是要递归吗?
24 6
8 3 12 7 9 7;
应该选 3,12,9;
我们是依次放入物品的,不论如何比较,当前得出的最大值不可能重复放同一个物品;
如第一个物品8;
一个循环后
v[8到24]=8;
v[1到7]=0;
二 3
v[11到24]=11;
v[8到10]=8;
v[3到7]=3;
v[1到2]=0;
以此类推;
举个例子
19 4
9 9 7 12
第一次 v[19]=9,第二次v[19]=18;第三次v[19]=18;第四次v[19]=v[7]+12=19;
我们发现不管如何到最后一个物品时结束任何容量的都会达到最大值,
但我们是从19到1,从19开始时v[12]=9,但不影响v[19]=v[7]+12=19;
假设 24=12+5+5+2;
物品 18 16 5 11 12 5 2;
到最后一个物品前v[24]=18+5=23;
但v[22]=22;
所以v[24]=v[22]+2=24;
假设 24=12+5+5+2;
物品 18 16 5 11 12 2 5;
v[22]=20;
但v[19]=19;
但又没有一种可能 如容量为24需要取最后一个数4,刚好24,但20也要取最后一个数4,达到最大20,答案是不可能,应为如果24容量的存储最大为选前面的和为20+4,那么到最后一个数前v[20]一定为20;