CodeVs 1014 解题报告

文章标题:Code_Vs_1014】解题报告

作者 :SinTASO

题目描述 

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

【错解】

记 D[i] 为容量为 的箱子的最小剩余空间赋初值为 i整型一维数组

记 A[i] 为编号为 的物品的给定占用空间由输入流读入整型一维数组

动态规划:

初状态:i=0

末状态:i=V

状态转移方程:D[i]=Min{ D[i - A[j]] if i>=A[j] } , j[1 , N];

输出答案:D[V]

【反思】

这段程序忽视了“每个物体只能被装进去一次”的隐藏条件。例如,在问题中将物体i装入背包,问题A变为了问题 A的子问题B,假定此次结果最优:那么如果子问题B的最优解在产生时便已将物体 装入了背包,在问题A的最优解中,物体i装入了两次——不符合条件。

【正解】

D[ i , j ] 为前 个物体不超过 的最大占用空间,赋初值为0。(整型二维数组)

记 A[i] 为编号为 的物品的给定占用空间由输入流读入整型一维数组

动态规划:

初状态:i=1j=1..V;

末状态:i=Nj=1..V;

状态转移方程:D[i , j]=Max{D[i - 1 , j] , if j>=A[i] ? D[i - 1 , j - A[i]] + A[i] : 0};

输出答案:V - D[N , V]

【总结】

这道题属于“01背包”类型,程序的“状态转移方程”就是不断地在“装”和“不装”两种情况中寻找最优解。

Pascal实现】

  

 1 Program Codevs1014;
 2 Const maxv=20000;
 3       maxn=30;
 4 Var A:array[0..maxn] of longint;
 5     D:array[0..maxn,0..maxv] of longint;
 6     n,v,i,j,k:longint;
 7   Function bigger(a,b:longint):longint;
 8   begin
 9     if a<b then exit(b);
10     exit(a);
11   end;
12 Begin
13    readln(v);
14    readln(n);
15    for i:=1 to n do readln(A[i]);
16    fillchar(D,sizeof(D),0);
17    for i:=1 to n do
18      for j:=1 to v do
19        if j>=A[i]
20          then D[i,j]:=bigger(D[i-1,j],D[i-1,j-A[i]]+A[i])
21          else D[i,j]:=D[i-1,j];
22    writeln(v-D[n,v]);
23 End.

 

 

 

posted @ 2015-08-04 13:55  Leo_Chenxi  阅读(178)  评论(0编辑  收藏  举报