题目来源:https://www.nowcoder.com/questionTerminal/fe298c55694f4ed39e256170ff2c205f
题目:
有这样一道智力题:“某商店规定:三个空汽水瓶可以换一瓶汽水。小张手上有十个空汽水瓶,她最多可以换多少瓶汽水喝?”答案是5瓶,方法如下:先用9个空瓶子换3瓶汽水,喝掉3瓶满的,喝完以后4个空瓶子,用3个再换一瓶,喝掉这瓶满的,这时候剩2个空瓶子。然后你让老板先借给你一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。如果小张手上有n个空汽水瓶,最多可以换多少瓶汽水喝?
输入描述:
输入文件最多包含10组测试数据,每个数据占一行,仅包含一个正整数n(1<=n<=100),表示小张手上的空汽水瓶数。n=0表示输入结束,你的程序不应当处理这一行。
输出描述:
对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出0。
示例:
输入
3
10
81
0
输出
1
5
40
本题之前没有做出来。
看到有两种解法:
解法一:
解法一的思路是通过数学分析,发现最多可以换到的汽水瓶数为输入时的瓶数除 2,例如 如果输入为 3,输出就为 1;输入为 10,输出为 5 等。
个人认为这是通过观察规律得到的,暂时没有想到或看到数学证明。
优点:代码量少;
缺点:没有严格的数学证明;
1 #include<iostream>
2 using namespace std;
3
4 int main()
5 {
6 int n;
7
8 while(cin >> n)
9 {
10 if (n <= 0 || n > 100)
11 {
12 break;
13 }
14 else
15 {
16 cout << n / 2 << endl;
17 }
18 }
19
20 return 0;
21 }
解法二:
解法二通过数学分析,有严谨的数学推导,发现是一个递归问题,我猜测本题的出题思路也是这样。
优点:有严谨的数学推导;直观;
缺点:代码量较解法一多;
/*
递归问题
3 个瓶子可以换 1 瓶水,剩下 1 个空瓶子;
2 个瓶子可以换 1 瓶水,剩下 0 个空瓶子;
1 个瓶子可以换 0 瓶水。
f(1) = 0 // 喝到 0 瓶水
f(2) = 1 // 喝到 1 瓶水,剩下 0 个空瓶子
f(3) = 1 // 喝到 1 瓶水,剩下 1 个空瓶子
f(4) = f(2)+1 // 4 个瓶子,其中 3 个可以换 1 瓶水, 剩下 2 个空瓶子,所以是 f(2) + 1
f(5) = f(3)+1 // 5 个瓶子,其中 3 个瓶子换 1 瓶水, 剩下 3 个空瓶子,所以是 f(3) + 1
...
f(n) = f(n-2)+1 */
1 #include <iostream>
2
3 using namespace std;
4
5 int f(int n)
6 {
7 if(n==1) return 0;
8 if(n==2) return 1;
9 return f(n-2)+1;
10 }
11
12 int main()
13 {
14 int n;
15 while(cin >> n){
16 if(n == 0 || n < 0 || n > 100)
17 break;
18 cout<<f(n)<<endl;
19 }
20 return 0;
21 }
解法三:
解法三是更加自然和直接的方法,通过判断可能的条件,写出判断的函数
优点:更加直观;
缺点:代码量多;
1 #include <iostream>
2 using namespace std;
3
4
5 void helper(int &n,int &result){
6 if(n == 1){
7 return;
8 }//if
9 if(n == 2){
10 ++result;
11 return;
12 }//if
13 result += n / 3;
14 n = n % 3 + n / 3;
15 helper(n,result);
16 }
17
18 int Drink(int n){
19 if(n <= 1){
20 return 0;
21 }//if
22 if(n == 2){
23 return 1;
24 }//if
25 int result = 0;
26 helper(n,result);
27 return result;
28 }
29
30
31 int main(){
32 int n;
33
34 while(cin >> n && n > 0 && n < 100){
35 cout << Drink(n) << endl;
36 }
37 return 0;
38 }