首次在LintCode上做了一個打敗了100%提交的答案,一定要紀念一下
下面進入正題:揹包問題-LintCode
問題描述:
在n個物品中挑選若干物品裝入揹包,最多能裝多滿?假設揹包的大小爲m,每個物品的大小爲A[i]
注意事項:不可以將物品進行切割。
樣例說明:
如果有4個物品[2, 3, 5, 7]
如果揹包的大小爲11,可以選擇[2, 3, 5]裝入揹包,最多可以裝滿10的空間。
如果揹包的大小爲12,可以選擇[2, 3, 7]裝入揹包,最多可以裝滿12的空間。
函數需要返回最多能裝滿的空間大小。
問題分析:首先,我們可以先將數組進行排序,然後從某一個開始,不斷地向後拾取元素放入揹包中,知道不能放入爲止
使用到的算法是深度優先算法
代碼實現:
/**
* @author 作者 John L:
* @version 創建時間:May 10, 2018 10:16:28 PM
*/
public class TestBackpack {
@Test
public void test(){
int[] A = new int[]{828,125,740,724,983,321,773,
678,841,842,875,377,674,144,340,467,625,916,
463,922,255,662,692,123,778,766,254,559,480,483,904,
60,305,966,872,935,626,691,832,998,508,657,215,162,858,
179,869,674,452,158,520,138,847,452,764,995,600,568,92,
496,533,404,186,345,304,420,181,73,547,281,374,376,454,
438,553,929,140,298,451,674,91,531,685,862,446,262,477,
573,627,624,814,103,294,388};
System.out.println(backPack(5000, A));
}
public int backPack(int m, int[] A) {
//先計算數組所有元素的和,如果所有元素加起來都小於m,就沒有必要繼續計算了
int temp = 0;
for (int i : A) temp += i;
if (temp <= m) return temp;
//先給數組進行排序,因爲本題的重點不是排序算法,所以直接調用java自帶的排序算法省時省力
Arrays.sort(A);
//一開始,我們可以從index=0開始拾取,揹包中已有的爲0
return backPack(A, m, 0, 0);
}
/**
* @param array 已經排序好了的數組
* @param total 揹包的大小
* @param indexFrom 只能從index後面拾取元素放入揹包
* @param currentCount 揹包中已經裝入的大小
* @return 在array數組中,從indexFrom開始到length-1所能拾取的最大大小(這個值一定要小於total-currentCount)
*/
private int backPack(int[] array, int total, int indexFrom, int currentCount){
int max = currentCount;
//因爲這是個排序數組,如果某一個元素的大小已經大於空閒大小,則說明不用往後面繼續計算了
for (int i = indexFrom; i < array.length && array[i] <= total - currentCount; i ++){
//我們拾取第i個放到包裏面,然後從第i+1個開始,繼續拾取元素填充包
int temp = backPack(array, total, i + 1, currentCount + array[i]);
//如果拾取到某一個元素後,正好能裝滿揹包,則可以直接返回裝滿的大小
if (temp == total) return total;
//如果當前策略的大小大於以前的值,則更新最大值
max = max >= temp ? max : temp;
}
return max;
}
}