牛客网 - 汽水瓶问题
题目来源: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 }