临沂九州超市营业时间:擅长pascal程序的高手、菜鸟(管他什么的)进来看看(要加分)

来源:百度文库 编辑:杭州交通信息网 时间:2024/05/03 22:47:39
题四 装箱问题(30分)
问题描述
有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30=,每个物品有一个体积(正整数)。

要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

样例

输入:

24 一个整数,表示箱子容量

6 一个整数,表示有n个物品

8 接下来n行,分别表示这n 个物品的各自体积

3

12

7

9

7

输出:

0 一个整数,表示箱子剩余空间。

大家加油哦!希望能附上程序,我的分并不少哦!到时候追加分数。

这个是背包问题~~我来回答
如果按照物品序号依次考虑装箱顺序的话,则问题具有明显的阶段特征。问题是当前阶段的剩余空间最小,并不意味下一阶段的剩余空间也一定最小,即该问题并不具备最优子结构的特征。但如果将装箱的体积作为状态的话,则阶段间的状态转移关系顺其自然,可使得最优化问题变为判定性问题。设状态转移方程
f[i,j]——在前i个物品中选择若干个物品(必须包括物品i)装箱,其体积正好为j的标志。显然f[i,j]=f[i-1,j-box[i]],即物品i装入箱子后的体积正好为j的前提是f[i-1,j-box[i]]=true。初始时,f[0,0]=true(1≤i≤n,box[i]≤j≤v)。
由f[i,j]=f[i-1,j-box[i]]可以看出,当前阶段的状态转移方程仅与上一阶段的状态转移方程攸关。因此设f0为i-1阶段的状态转移方程,f1为i阶段的状态转移方程,这样可以将二维数组简化成一维数组。我们按照下述方法计算状态转移方程f1:
fillchar(f0, sizeof(f0),0); {装箱前,状态转移方程初始化}
f0[0]←true;
for i←1 to n do {阶段i:按照物品数递增的顺序考虑装箱情况}
begin
f1←f0; {i阶段的状态转移方程初始化}
for j←box[i] to v do {状态j:枚举所有可能的装箱体积}
if f0[j-box[i]] then f1[j]←true;{若物品i装入箱子后的体积正好为j,则物品i装入箱子}
f0←f1; {记下当前装箱情况}
end;{for}

经过上述运算,最优化问题转化为判定性问题。再借用动态程序设计的思想,计算装箱的最大体积 k= 。显然最小剩余空间为v-k:
for i←v downto 0 do {按照递减顺序枚举所有可能的体积}
if f1[i] then begin {若箱子能装入体积为i的物品,则输出剩余空间v-i,并退出程序}
writeln(v-i); halt
end;{then}
end.{for}
writeln(v); {在未装入一个物品的情况下输出箱子体积}

我又写了个回溯的方法

容量为v的箱子究竟应该装入哪些物品可使得剩余空间最小。显然在n个物品的体积和小于等于v的情况下,剩余空间为v-n个物品的体积和。但在n个物品的体积和大于v的情况下,没有一种可以直接找到问题解的数学方法。无奈之下,只能采用搜索的办法。设
a和s为箱子的体积序列。其中a[i]为箱子i的体积,s[i]为前i个箱子的体积和 (1≤i≤n);
best为目前所有的装箱方案中最小的剩余空间。初始时best=v;
确定搜索的几个关键因素:
状态(k,v’):其中k为待装入箱子的物品序号,v’为箱子目前的剩余空间。
目标v’<best:若箱子的剩余空间为目前为止最小,则best调整为v’(best←v);
边界条件(v’-(s[n]-s[k-1]))≥best:即便剩下的物品全部装入箱子(未装物品的体积和为s[n]-s[k-1]),其剩余空间仍不小于best,则放弃当前方案,回溯;
搜索范围:在未装入全部物品的前提下(k≤n),搜索两种可能情况:
l 若剩余空间装得下物品k(v’≥a[k]),则物品k装入箱子,递归计算子状态(k+1,v’-a[k]);
l 物品k不装入箱子,递归计算子状态(k+1,v’);
我们用递归过程search(k,v)描述这一搜索过程:
procedure search(k,v:integer); {从状态(k,v)出发,递归计算最小剩余空间}
begin
if v<best then best←v; {若剩余空间为目前最小,则调整best}
if v-(s[n]-s[k-1])>=best {若箱子即便装下全部物品,其剩余空间仍不小于best,则回溯}
then exit;
if k<=n {在未装入全部物品的前提下搜索两种可能情况}
then begin
if v>=a[k] {若剩余空间装得下物品k,则物品k装入箱子,递归计算子状态}
then search(k+1,v-a[k]);
search(k+1,v); {物品k不装入箱子,递归计算子状态}
end;{then}
end;{search}

主程序如下:
读箱子体积v;
读物品个数n;
s[0] ←0; {物品装入前初始化}
for i←1 to n do {输入和计算箱子的体积序列}
begin
读第i个箱子的体积a[i];
s[i]←s[i-1]+a[i];
end;{for}
best←v; {初始时,最小剩余空间为箱子体积}
if s[n]<=v then best←v-s[n] {若所有物品能全部装入箱子,则剩余空间为问题解}
else search(1,v); {否则从物品1出发,递归计算最小剩余空间}
输出最小剩余空间best;

这个是我用DP做的
var a:array[1..30] of integer;
f0,f1:array[-20000..20000] of boolean;
v,i,j,k,m,n:integer;
begin
readln(v);
readln(n);
fillchar(f0,sizeof(f0),false);
fillchar(f1,sizeof(f1),false);
f0[0]:=true;
f1[0]:=true;
for i:=1 to n do readln(a[i]);
for i:=1 to n do
begin
f1:=f0;
for j:=a[i] to v do
if f0[j-a[i]] then f1[j]:=true;
f0:=f1
end;
for i:=v downto 0 do
if f1[i] then begin writeln(v-i);halt;end;
end.