標籤:
文章標題:【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 Begin13 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 do18 for j:=1 to v do19 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.
【Code_Vs_1014】解題報告