文章标题:【Code_Vs_1014】解题报告与总结
作者 :SinTASO
题目描述
有一个箱子容量为V(正整数,0<=V<=20000),同时有N个物品(0<N<=30),每个物品有一个体积(正整数)。要求N个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。
【错解】
记 D[i] 为容量为 i 的箱子的最小剩余空间,赋初值为 i。(整型一维数组)
记 A[i] 为编号为 i 的物品的给定占用空间,由输入流读入。(整型一维数组)
动态规划:
初状态:i=0;
末状态:i=V;
状态转移方程:D[i]=Min{ D[i - A[j]] if i>=A[j] } , j∈[1 , N];
输出答案:D[V];
【反思】
这段程序忽视了“每个物体只能被装进去一次”的隐藏条件。例如,在问题A 中将物体i装入背包,问题A变为了问题 A的子问题B,假定此次结果最优:那么如果子问题B的最优解在产生时便已将物体 i 装入了背包,在问题A的最优解中,物体i装入了两次——不符合条件。
【正解】
记D[ i , j ] 为前 i 个物体不超过 j 的最大占用空间,赋初值为0。(整型二维数组)
记 A[i] 为编号为 i 的物品的给定占用空间,由输入流读入。(整型一维数组)
动态规划:
初状态:i=1,j=1..V;
末状态:i=N,j=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.
时间: 2024-11-05 20:26:43