一道華爲簡單算法題記錄-汽水瓶

一道華爲簡單算法題記錄-汽水瓶

背景

今天公司同事提到了面試一位新人的時候提出的華爲的一道題,感覺有點意思,記錄下吧。
假設一瓶汽水售價1元,3個瓶蓋可以換一瓶汽水,2個瓶子可以換一瓶汽水,問20元可以喝多少汽水。

解法描述

看到這個題目,最直接的做法,就是寫個程序,模擬買汽水-換汽水的過程,直到剩餘的瓶蓋或者瓶體買不到汽水。

然而這樣寫似乎有點太麻煩了,依稀記得這種換汽水問題是小學的必考題,直到初中學了方程才學會智能的解法。小學時我們經常會遇到這樣的問題,汽水1元,2個瓶子可以換一瓶汽水,10元能喝到多少瓶汽水。然後就可以在紙上模擬整個過程了,答案是20瓶。這種題技巧是如果最後只剩下一個空瓶子的時候要向老闆借一瓶,然後湊2個瓶子換一瓶汽水,再把最後的2個瓶子還給老闆。

到了初中,我們學會了列方程解決問題。就換了一種思路,不再一步步推算了。其實從題目描述來看,瓶子和汽水都是有價值的,而作爲消費者我們的目的是爲了喝汽水,所以爲了喝到最多的汽水,我們要把所有的錢都換成汽水。
設汽水的價值是x,汽水瓶子的價值是y。
則有
{x+y=12y=x+y \left\{ \begin{array}{lr} x + y = 1 \\ 2y= x + y \end{array} \right.
從而解得
x=12y=12 \begin{array}{lr} x = \dfrac{1}{2}\\ y = \dfrac{1}{2} \end{array}
所以能喝到的汽水是10/12=2010/\dfrac{1}{2}=20瓶。
那麼華爲的題目也可以用類似的辦法做。設瓶蓋的價格是x,瓶體的價格是y,汽水的價格是z。
那麼我們可以列出下面方程組
3x=x+y+z2y=x+y+z1=x+y+z \begin{array}{lr} 3x &= x+y+z\\ 2y &= x+y+z\\ 1 & = x + y + z \end{array}
解得
x=13y=12z=16 \begin{array}{lr} x = \dfrac{1}{3}\\ y = \dfrac{1}{2}\\ z= \dfrac{1}{6} \end{array}
所以如果我們可以把錢全部轉化爲汽水的話,換句話說,允許向老闆賒賬的話則可以喝20/16=12020/\dfrac{1}{6}=120瓶。
然而,這道題其實不允許賒賬。所以直接return 6*x是不行的。
所以老老實實寫程序

#include <stdio.h>
int main(){
int money;
const  int price = 1;
while(1){
	scanf("%d",&money);
	int result,hat,body;
	result= money/price;
	hat = result;
	body = result;
	int tmp = 0;
	while(!(hat<3 && body < 2)){
		tmp = hat/3 + body/2;
		result += tmp;
		hat = hat % 3 + tmp;
		body = body % 2 + tmp;
	}
	printf("%d\n",result);
}
return 0;
}

進一步思考

我們開始定義一下喝汽水的步驟,
(1) 首先將錢換成汽水,將汽水喝完。
(2) 儘可能多的將手中所有的瓶子和瓶蓋換成汽水,如果換不了則結束。
(3) 繼續喝完所有汽水,然後重複步驟二。
按照上述步驟喝汽水,我們可以保證能喝到最多的汽水,最後剩餘的瓶子和瓶蓋也肯定換不了汽水。
然後開始考慮問題複雜在哪裏,在不允許賒賬的情況下,最後可能會剩下瓶子和瓶蓋轉化不成汽水,所以肯定達不到120瓶。
那麼最後會剩幾個瓶子和瓶蓋呢。分類討論下
(1)瓶子數大於等於2或者瓶蓋大於等於3的情況。不可能出現,因爲此時還可以繼續換汽水。
(2)只剩下瓶子或者只剩下瓶蓋的情況。不可能出現,假設按照上述步驟喝,到達最後一步不能再換取新的汽水之前,肯定至少喝完了一瓶汽水,那麼肯定剩下至少一個瓶子喝一個瓶蓋。
(3)1個瓶子,1個瓶蓋。只剩一個瓶子一個瓶蓋,說明在到達最後一步之前的喝汽水的步驟時,我們既沒有瓶蓋也沒有瓶子,只有一瓶汽水。那麼在獲得這一瓶汽水之前的換汽水的步驟裏,肯定只有3個瓶蓋或者2個瓶子,這喝我們的情況2是一樣的,顯然是不可能存在的。所以這一瓶汽水只能是在步驟一中花錢買的,即只有1元錢的時候的情況。 所以當只有1元錢時,我們最終會剩下一個瓶子和瓶蓋,一共價值爲12+13=56\dfrac{1}{2}+\dfrac{1}{3}=\dfrac{5}{6}元。那麼只有16\dfrac{1}{6}元轉化爲了汽水,也就是隻能喝一瓶。
(4)1個瓶子,2個瓶蓋。 經過上述討論,只剩下了這一種情況,即只要不是1元錢,肯定最後剩下1個瓶子2個瓶蓋,價值爲12+23=76\dfrac{1}{2}+\dfrac{2}{3}=\dfrac{7}{6}元。所以最後相比較可以賒賬的情況,會少買7瓶。
下面寫程序:

#include <stdio.h>
int main(){
int money;
const  int price = 1;
while(1){
	scanf("%d",&money);
	if(money == 1) printf("1\n");
	else printf("%d\n",6 * money - 7);
}
return 0;
}

推廣

假設我們有m元,汽水價格爲p,h個瓶蓋可以換取一瓶汽水,b個瓶子可以換一瓶汽水。那麼可以喝多少瓶汽水呢。
暫時還沒有找到很好的規律,隨着h和b的增大,可能最終的情況多了起來。如果每次輸入都進行更改的話,能想到的還是隻是去模擬買汽水的步驟。類似於第一份代碼,只不過,把hat和body的限制換成輸入。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章