經典數學問題「空瓶換酒」求解(C C )

2021-08-18 07:59:40 字數 3204 閱讀 9691

經典數學問題「空瓶換酒」:某啤酒店可用a(>0)個空啤酒瓶換b(

通常這類問題希望我們要「投機取巧」,即先找店家或他人借空瓶,換酒喝完後再如數歸還

為求全面,本人分別對「允許借空瓶」與「不允許借空瓶」兩種情況進行推導

(一)允許借空瓶:

能借到空瓶我們可以盡可能做到物盡其用

每換一次需要a個空瓶,而換來的酒喝完後又有b個空瓶,實際每次兌換空瓶減少(a-b)個

於是n個空瓶總共可兌換:n/(a-b) 次(式中除法為整數除法,商為兌換次數,餘數則是最後剩餘的空瓶數)

由於每次兌換可得到b瓶啤酒,於是共可兌換n/(a-b)*b瓶啤酒

一共能喝到的啤酒數當然也就為(n + n/(a-b)*b)瓶了

(二)不允許借空瓶

如果沒人願意借給你空瓶,此時只能「自力更生」了

若n小於a,很明顯一次也兌換不了,一共能喝的也就是買的那n瓶啤酒

若n不小於a,一旦剩餘空瓶數小於a,則兌換結束

為方便計算,預留a個空瓶,先兌換其餘(n-a)個空瓶,於是可從預留的a個空瓶裡去「借」,喝完再「歸還」

根據「允許借空瓶」情況公式,(n-a)個空瓶總共可兌換:(n-a)/(a-b) 次(同上,式中除法表示整數除法)

由於預留的a個空瓶最後還可再進行一次兌換,故總兌換總次數為:(n-a)/(a-b)+1,化簡後為(n-b)/(a-b) 次

最後預留的a個空瓶換的b瓶啤酒喝完後還會得到b個空瓶,故最後剩餘的空瓶數為上式餘數加b

由於每次兌換可得到b瓶啤酒,於是共可兌換(n-b)/(a-b)*b瓶啤酒

一共能喝到的啤酒數當然也就為(n + (n-b)/(a-b)*b)瓶了

為將以上公式通用化,當n小於b時,b取值同n

基於上述推導,本人開發了求解「空瓶換酒」問題的win32應用程式,開發語言c/c++(結合windows sdk)

程式介面如圖:

程式主要**如下:

#include "stdafx.h"

#include #include #pragma comment(lib, "comctl32.lib")

#include #pragma comment(lib, "shlwapi.lib")

#define input_limit 9

static hwnd hedita;

static hwnd heditb;

static hwnd heditn;

static hwnd hbuttoncalc;

static hwnd heditres1;

static hwnd heditres2;

static hwnd heditres3;

static void clearresults()

}int_ptr callback dialogproc(hwnd hwnddlg, uint umsg, wparam wparam, lparam lparam)

break;

case wm_command:

break;

case makewparam(idc_edit_a, en_change):

break;

case makewparam(idc_edit_b, en_change):

break;

case makewparam(idc_edit_n, en_change):

break;

case makewparam(idc_check_borrow, bn_clicked):

break;

case makewparam(idc_button_calc, bn_clicked): //計算部分

if (getwindowtextlength(heditb) <= 0)

if (getwindowtextlength(heditn) <= 0)

uint a = getdlgitemint(hwnddlg, idc_edit_a, null, false);

if (!a)

uint b = getdlgitemint(hwnddlg, idc_edit_b, null, false);

if (b >= a)

uint n = getdlgitemint(hwnddlg, idc_edit_n, null, false);

uint u1, u2, u3;

if (isdlgbuttonchecked(hwnddlg, idc_check_borrow) == bst_unchecked)

else

tchar sztext[12];

wnsprintf(sztext, 12, text("%u"), u1);

setwindowtext(heditres1, sztext);

wnsprintf(sztext, 12, text("%u"), u2 + u3);

setwindowtext(heditres2, sztext);

wnsprintf(sztext, 12, text("%u"), n + u1 * b);

setwindowtext(heditres3, sztext);

enablewindow(hbuttoncalc, false);

return (int_ptr)true;

} break;

} }break;

} return (int_ptr)false;

}extern "c" void startup()

exitprocess((uint)dialogboxparam(null, makeintresource(idd_dialog), null, dialogproc, (lparam)0));

}

結論1、將「空瓶換酒」問題公式化,分別推導了「允許借空瓶」與「不允許借空瓶」兩種情況計算公式

2、根據推導的計算公式開發了計算「空瓶換酒」問題的程式,比使用迴圈方式計算的程式簡潔且高效

3、通過推導與觀察可發現,購買n瓶啤酒大約可以喝到a/(a-b)*n瓶,也就是約為購買數量的a/(a-b)倍(注:這裡不再是整數除法),且a越大或a與b越接近時此倍數越大。即使按常見的3:1比例兌換,買668瓶就能喝到1000瓶,一般人是該滿意了哈~

海盜分酒(數學問題)

海盜分酒 題目描述 有一群海盜 不多於 20人 在船上比拼酒量。過程如下 開啟一瓶酒,所有在場的人平分喝下,有幾個人倒下了。再開啟一瓶酒平分,又有倒下的,再次重複 直到開了第 4瓶酒,坐著的已經所剩無幾,海盜船長也在其中。當第 4瓶酒平分喝下後,大家都倒下了。等船長醒來,發現海盜船擱淺了。他在航海日...

經典數學問題 Nim遊戲

nim遊戲是博弈論中最經典的模型,是組合遊戲 combinatorial games 的一種,屬於 impartial combinatorial games 以下簡稱icg 滿足以下條件的遊戲是icg 1 有兩名選手 2 兩名選手交替對遊戲進行移動 move 每次一步,選手可以在 一般而言 有限的...

經典數學問題 Nim遊戲

nim遊戲是博弈論中最經典的模型,是組合遊戲 combinatorial games 的一種,屬於 impartial combinatorial games 以下簡稱icg 滿足以下條件的遊戲是icg 1 有兩名選手 2 兩名選手交替對遊戲進行移動 move 每次一步,選手可以在 一般而言 有限的...