一、題目描述
有這樣一道智力題:“某商店規定:三個空汽水瓶可以換一瓶汽水。小張手上有十個空 汽水瓶,她最多可以換多少瓶汽水喝?”答案是5瓶,方法如下:先用9個空瓶子換3瓶汽水,喝掉3瓶滿的,喝完以後4個空瓶子,用3個再換一瓶,喝掉這瓶滿 的,這時候剩2個空瓶子。然後你讓老闆先借給你一瓶汽水,喝掉這瓶滿的,喝完以後用3個空瓶子換一瓶滿的還給老闆。如果小張手上有n個空汽水瓶,最多可以換多少瓶汽水喝?
二、輸入描述
輸入檔案最多包含10組測試資料,每個資料佔一行,僅包含一個正整數n(1<=n<=100),表示小張手上的空汽水瓶數。n=0表示輸入結束,你的程式不應當處理這一行。
三、輸出描述
對於每組測試資料,輸出一行,表示最多可以喝的汽水瓶數。如果一瓶也喝不到,輸出0。
四、輸入輸出示例
輸入例子:
3
10
81
0
輸出例子:
1
5
40
五、分析思路
1.按照三個瓶子為主要線索進行分析。
顯然,我們可以知道,假設有N個空瓶子,可以兌換的飲料瓶數為N/3瓶,還剩餘N - 3 * (N / 3) 個空瓶子。此時,由於兌換的汽水喝完後又會有新的空瓶子,所以進行一次兌換並且 喝完汽水後的空瓶子數量為T = N/3 + N - 3 * (N / 3),如果T = 0 或者 T = 1,則無法再兌換汽水,即問題結束;如果T = 2,則可以再兌換一瓶汽水,喝完了問題也就結束了;否則,又可以按照之前的思路進行下一步操作,即之前的N個空瓶子被替換成了N/3 + N - 3 * (N / 3),問題的規模發生了變化,思路沒有變化。很順其自然的,我們就想到了遞迴,使用遞迴來求解這個
問題。具體程式碼如下:
import java.util.Scanner; import java.util.List; import java.util.ArrayList; public class SoftDrink { /** * drunk表示此次可以喝的汽水瓶數 * bottleNumber表示此次兌換剩餘的空瓶子數量 */ public static int solution(int drunk, int bottleNumber) { // 總共的空瓶子數量 int total = drunk + bottleNumber; if (total > 2) { // 空瓶子總數大於2,問題可以繼續求解 return drunk + solution(total / 3, total - 3 *(total / 3)); } else if (total == 2) { // 兌換一瓶汽水,結束 return drunk + 1; } else { // 無法兌換汽水,結束 return drunk; } } public static void main(String[] args) { List<Integer> inputs = new ArrayList<Integer>(); Scanner scan = new Scanner(System.in); while (true) { int input = scan.nextInt(); if (0 == input) { break; } else { inputs.add(input); } } scan.close(); for (int input : inputs) { int number = solution(input / 3, input - 3 *(input / 3)); System.out.println(number); } } }
2.按照兩個瓶子為主要線索進行分析。
根據題意,有兩個空瓶子,就可以找老闆再要一瓶汽水,喝完後再兌換成飲料還給老闆。所以,我們可以知道,其實只要兩個瓶子就可以換一瓶汽水(不包含瓶子,該汽水喝完後的空瓶子不能再次進行兌換,可以看成喝完後就直接丟棄),所以問題就變得十分的簡單了。具體程式碼如下:
import java.util.Scanner; import java.util.List; import java.util.ArrayList; public class BottleQuestion { public static int solution(int n) { int sum = 0; if (n <= 1) { //一個瓶子不能換 sum = 0; } else { //兩個以上可以換 sum = n / 2; //直接除以2,因為int型別所以多一個瓶子也不影響 } return sum; } public static void main(String[] args) { List<Integer> inputs = new ArrayList<Integer>(); Scanner scan = new Scanner(System.in); while (true) { int input = scan.nextInt(); if (0 == input) { break; } else { inputs.add(input); } } scan.close(); for (int input : inputs) { int number = solution(input); System.out.println(number); } } }
六、總結
同樣一個問題,換不同的思路可以有不同的解決辦法,第二種思路的程式碼比第一種思路的程式碼量少很多,所以,解決一個問題時,思路往往是最重要的。謝謝各位園友觀看~