竞赛题

hit56工作室 2007-07-25 08:52:00
[问题描述]
有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积 (正整数)。要求从m个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。
[样例]
输入:
24 一个整数,表示箱子容量
6 一个整数,表示有n个物品
8 接下来n行,分别表示这n个物品的各自体积。
3
12
7
9
7
输出:
0 一个整数,表示箱子剩余空间。
...全文
361 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
languagec 2007-07-26
  • 打赏
  • 举报
回复
装箱问题算法分析
装箱问题算法分析
作者:fisher_jiang 来源: 发表时间:2006-06-21 浏览次数: 1513 字号:大 中 小
装箱问题
[问题描述]
有一个箱子容量为V(正整数,0≤V≤20000),同时有n个物品(0≤n≤30),每个物品有一个体积(正整数)。要求从n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

[样例]

输入: 24 一个整数,表示箱子容量
6 一个整数,表示有n个物品
8 接下来n行,分别表示这n个物品的各自体积。
3
12
7
9
7

输出: 0 一个整数,表示箱子剩余空间

算法分析:
本题是经典问题:0-1背包的特殊例子(加强了已知条件)。用整形数组volume存储各件物品的体积,用布尔型函数h(i,k)表示前i个物品通过组合能否恰好装满容量k的空间,则考虑第i件物品,如果没有被选中,则问题转化为h(i-1,k);如果第i件物品被选中了,则问题转化为h(i-1,k-volume[i]),因此有如下的表达式:
h(i,k)=h(i-1,k-volume[i]) || h(i-1,k);

k从V开始递减,判断h(n,k)是否为真,第一个符号要求的k即为剩余空间最小时消耗的体积。
如果此时直接编写程序,就要定义一个二维数组,空间复杂度时n*v,注意到了n,v的取值范围很大,所以用二维数组存储就会有问题。


我们注意到,h(i,k)的取值仅与h(i-1,0)~h(i-1,k)有关,且如果h(i-1,k)=true,必然有h(i,k)=true,h(i,k)的值存在继承性,而程序结束时,我们也只关心h(n,k),因此,我们可以用一维数组h(k)来存储中间信息。为了避免重复计算,可以让k从大到小变化,为了避免出现负数,k的变化范围为v~volume[i].

示例程序:

#include<iostream>
#include<cstring>
using namespace std;
int v,n;
int volume[31];//存储n件物品的体积
int h[20001];//h[i]=1,表示n件物品通过某种组合,所构成的体积和正和等于i;
//h[i]=0,表示n件物品无论如何组合,体积和都无法等于i
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
int v,n,i,j,k;
while(cin>>v>>n)
{
for(i=1;i<=n;i++)
cin>>volume[i];
memset(h,0,sizeof(h));
h[0]=1;
for(i=1;i<=n;i++)
for(k=v;k>=volume[i];k--)
h[k]=h[k]||h[k-volume[i]];
j=v;
while(j>0&&h[j]==0)
j--;
cout<<v-j<<endl;
}
return 0;
}


jeffrey_nupt 2007-07-25
  • 打赏
  • 举报
回复
OI吗?和2001年普及组第四题蛮像的……

可以用递归回溯解决啊……

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧