描述
有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积 (正整数)。要求从 n 个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。
格式
输入格式
第一行,一个整数,表示箱子容量;
第二行,一个整数,表示有n个物品;
接下来n行,分别表示这n个物品的各自体积。
输出格式
一个整数,表示箱子剩余空间。
分析
和之前一样,我们从决策入手,首先我们的决策和01背包一样,是当前物品是否放入,决策的策略是加入这件物品是否能让我们箱内的空间变的最小?为了更加清晰的定义出我们的策略,我们定义状态,该问题中我们的要素应该有两个,一个是序列i,还有一个是物品的体积v,从结论入手我们不难发现,我们需要定义的状态也应该是v,但是如果我们仅仅把要素v当作状态本身的话,那么我们在决策第i个物品是否放入的话,除了箱子剩下的体积已经放不下第i个物品时,其他情况只能的到“放入“这个唯一得结果,这明显是错误的,出现这样错误的原因时决策,是因为没有考虑到v这个要素(把它当做参数),综上我们的状态应该是一个把i和v当作参数,v当作本质的状态,我们定义状态f[i][c]为前i个物品在空间为c时的最大体积,这样下来我们发现其实和01背包是完全一样的问题。
//
// main.cpp
// 装箱问题
//
// Created by 张嘉韬 on 16/1/10.
// Copyright © 2016年 张嘉韬. All rights reserved.
//
#include <iostream>
#include <cstdio>
using namespace std;
int f[500][200100];
int max(int a,int b)
{
if(a>b) return a;
else return b;
}
int main(int argc, const char * argv[]) {
//freopen("/Users/zhangjiatao/Desktop/input.txt","r",stdin);
int v,n,w[500];
cin>>v>>n;
for(int i=1;i<=n;i++)
{
cin>>w[i];
}
for(int j=1;j<=v;j++)
{
if(j<w[1]) f[1][j]=0;
else f[1][j]=w[1];
}
for(int i=1;i<=n;i++)
{
f[i][0]=0;
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<=v;j++)
{
if(w[i]<=j)
{
f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+w[i]);
}
else
{
f[i][j]=f[i-1][j];
}
}
}
cout<<v-f[n][v];
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=v;j++)
// {
// cout<<f[i][j]<<" ";
// }
// cout<<endl;
// }
return 0;
}