题目链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1917
题目
1917:【01NOIP普及组】装箱问题
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 4117 通过数: 2443
【题目描述】
有一个箱子容量为V�(正整数,0≤V≤200000≤�≤20000),同时有n个物品(0≤n≤300≤�≤30),每个物品有一个体积(正整数)。要求从n�个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
【输入】
第一行是箱子的容量,第二行是n�(表示n�有n�个物品),接下来n�行是n�个物品的体积。
【输出】
最小空间
【输入样例】
24
6
8
3
12
7
9
7
【输出样例】
0
题目详解
f[i][j]:表示前i件物品装满了容量是j
以前f[i][j]=100 表示前i个人吃j个包子得到的最大价值为100
现在f[i][j]存放的是true和false,表示前i个人有没有吃完j个包子
f[i][j]=true表示前i件物品装满了容量是j的箱子,没有装满为false
f[i][j]关键看第i件物品背或不背
f[i][j]关键看第i件物品背或不背
不背: f[i-1][j]=0 1 0 1
背:f[i-1][j-w[i]]=0 0 1 1
f[i][j]=0, 1, 1, 1
f[j]= f[j] || f[j-w[i]];
上代码(此为01背包)
cpp
include<bits/stdc++.h>
using namespace std;
int main()
{
int i,j,f[20001]={0},n,v,w[10001],c,k;
cin>>v;
cin>>n;
for(i=1;i<=n;i++)
cin>>w[i];
f[0]=true;//边界!!默认容量为0的箱子什么都不装,是满的
//剩下的f[1]...[20001] 都是0,没有装满
for(i=1;i<=n;i++)
for(j=v;j>=w[i];j--)
f[j]=f[j]||f[j-w[i]];//以前是求最大
//前i件物品能不能装满容量为i的箱子
//情况一:前i-1件物品能装满,则f[j]必然为true
//情况二:前i-1件物品没装满,则要判断装入第i件物品,f[j-w[i]]=true,则结果f[j]为true
//只要有一个为true,就表示可以装满
for(k=v;k>=0;k--)
if(f[k]==true)//体积从大到小,第一个装满的最大容量
{
cout<<v-k<<endl;
return 0;//break;找到第一个最大的就结束了
//k=100,f[100]=false,....k=90,f[90]=true,所以第一个装满的是90
}
}
点赞关注收藏