問題描述:給定一個積分總point,給定多個產品,每個產品需要相應數目的積分,用數組convertPoint[]表示,每種產品的兌換數量用數組convertCount[]表示,求如何兌換積分使得剩餘積分最少。
示例:
input:
point = 19
convertPoint[] = {5,3}
output:
convertCount[] = {2,3}
解題思路:
問題還是很清晰明瞭的,我們採用的思想也很粗暴,嘗試每一種組合方式,如 {0,0}, {0,1}, {0,2}, {0,3}...保證組合積分總數<=point即可,求得各種方案中剩餘積分數量最少的組合。
關鍵難點在於產品數目的可變性,無法用固定的多個循環體來描述問題,一般這時候就需要用到遞歸了。
直接看代碼:
private static void calculateCash(int point,int i) {
while(tempCount[i]*convertPoint[i]<=point){
if(i<convertPoint.length-1) {
calculateCash(point-tempCount[i]*convertPoint[i],i+1);
}else {
if((point-tempCount[i]*convertPoint[i])<rest) {
System.arraycopy(tempCount,0, convertCount, 0, tempCount.length);
rest = point-tempCount[i]*convertPoint[i];
}
}
tempCount[i]++;
}
tempCount[i] = 0;
}
調用方法:
calculateCash(point,0);
需要兩個額外的輔助變量
1 int rest = convertPoint[0]; //表示最少的積分剩餘數
2 int tempCount[] = new int [convertPoint.length]; //用於表示目前的產品組合
優化:
對於最後一個產品數量可以不用從0開始向上加,直接取最大值;
即在此句if
if((point-tempCount[i]*convertPoint[i])<rest) {
前邊添加
tempCount[i] = point / convertPoint[i];
優化後代碼:
private static void calculateCash(int point,int i) {
while(tempCount[i]*convertPoint[i]<=point){
if(i<convertPoint.length-1) {
calculateCash(point-tempCount[i]*convertPoint[i],i+1);
}else {
tempCount[i] = point / convertPoint[i];
if((point-tempCount[i]*convertPoint[i])<rest) {
System.arraycopy(tempCount,0, convertCount, 0, tempCount.length);
rest = point-tempCount[i]*convertPoint[i];
}
}
tempCount[i]++;
}
tempCount[i] = 0;
}