0-1背包問題指的是有一個能裝w重的背包,和n個不同重量的物體,如何選擇物體才能盡可能地裝滿背包。
回溯的處理思想,有點類似枚舉搜索。我們枚舉所有的解,找到滿足期望的解。為了有規律地枚舉所有可能的解,避免遺漏和重復,我們把問題求解的過程分為多個階段。每個階段,我們都會面對一個岔路口,我們先隨意選一條路走,當發現這條路走不通的時候(不符合期望的解),就回退到上一個岔路口,另選一種走法繼續走。
public int maxW = Integer.MIN_VALUE; //存儲背包中物品總重量的最大值 // cw表示當前已經裝進去的物品的重量和;i表示考察到哪個物品了; // w背包重量;items表示每個物品的重量;n表示物品個數 // 假設背包可承受重量100,物品個數10,物品重量存儲在數組a中,那可以這樣調用函數: // f(0, 0, a, 10, 100) public void f(int i, int cw, int[] items, int n, int w) { if (cw == w || i == n) { // cw==w表示裝滿了;i==n表示已經考察完所有的物品 if (cw > maxW) maxW = cw; return; } f(i+1, cw, items, n, w);//不選擇放這個物體 f(i+1,cw + items[i], items, n, w);//選擇放這個物體 }
這里還可以在優化一下,當cw+items[i]>w時就可以不用再遞歸了。
public int maxW = Integer.MIN_VALUE; //存儲背包中物品總重量的最大值 // cw表示當前已經裝進去的物品的重量和;i表示考察到哪個物品了; // w背包重量;items表示每個物品的重量;n表示物品個數 // 假設背包可承受重量100,物品個數10,物品重量存儲在數組a中,那可以這樣調用函數: // f(0, 0, a, 10, 100) public void f(int i, int cw, int[] items, int n, int w) { if (cw == w || i == n) { // cw==w表示裝滿了;i==n表示已經考察完所有的物品 if (cw > maxW) maxW = cw; return; } f(i+1, cw, items, n, w); if (cw + items[i] <= w) {// 已經超過可以背包承受的重量的時候,就不要再裝了 f(i+1,cw + items[i], items, n, w); } }