【01背包】装箱问题

题目:装箱问题 rqnoj147

题目描述

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30=,每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

输入格式

输入:
第一行是一个整数v,表示箱子容量
第二行是一个整数n,表示有n个物品
接下来n行,分别表示这n 个物品的各自体积

输出格式

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

样例输入

样例输出

 

用一个bool f[i,j]表示前 i 个物品能否恰好表示出体积j ,第一个参数 i 可以用就地滚动省略

最后逆序扫描一次f[n][j] ,只要遇到true就停下,用总体积 — 当前体积j ,就是最少剩余体积

这里提供Pascal 二维数组的完整代码,和C++就地滚动的部分代码

Pascal Code

program rqnoj147;

var
  n,v:longint;
  a:array[0..30+10] of longint;
  f:array[0..30+10,0..20000+10] of boolean;

procedure init;
begin
  assign(input,'rqnoj147.in');
  assign(output,'rqnoj147.out');
  reset(input);
  rewrite(output);
end;
procedure outit;
begin
  close(input);
  close(output);
  halt;
end;

procedure readdata;
var
  i:longint;
begin
  read(v);
  read(n);
  for i:=1 to n do
    read(a[i]);
end;

procedure main;
var
  i,j:longint;
begin
  fillchar(f,sizeof(f),0);
  f[0,0]:=true;
  for i:=1 to n do
  begin
    for j:=0 to v do
    begin
      f[i,j]:=f[i-1,j];
      if (j>=a[i])and(f[i-1,j-a[i]]) then
        f[i,j]:=f[i-1,j-a[i]];
    end;
  end;
  for j:=v downto 0 do
    if f[n,j] then
    begin
      writeln(v-j);
      outit;
    end;
end;


begin
  init;
  readdata;
  main;
  outit;
end.

 

C++ Code(部分)

//动规
f[0]=true;
for(int i=1;i<=n;i++)
  for(int j=v;j>=a[i];j--)
    if(f[j-a[i]]) f[j]=f[j-a[i]];

//扫描
for(int j=v;j>=0;j++)
  if(f[j])
    {printf("%d",v-j);exit(0);}

 

posted @ 2012-08-19 08:18  jiangzh  阅读(542)  评论(0编辑  收藏  举报