经典数学问题“空瓶换酒”求解(C/C++)
经典数学问题“空瓶换酒”:某啤酒店可用a(>0)个空啤酒瓶换b(<a)瓶啤酒,某人一次购买n瓶啤酒,问其最多能够喝多少瓶啤酒?
通常这类问题希望我们要“投机取巧”,即先找店家或他人借空瓶,换酒喝完后再如数归还
为求全面,本人分别对“允许借空瓶”与“不允许借空瓶”两种情况进行推导
(一)允许借空瓶:
能借到空瓶我们可以尽可能做到物尽其用
每换一次需要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 <Windows.h>
#include <Commctrl.h>
#pragma comment(lib, "Comctl32.lib")
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")#define INPUT_LIMIT 9static HWND hEditA;
static HWND hEditB;
static HWND hEditN;
static HWND hButtonCalc;
static HWND hEditRes1;
static HWND hEditRes2;
static HWND hEditRes3;static VOID ClearResults()
{if (!IsWindowEnabled(hButtonCalc)){SetWindowText(hEditRes1, TEXT(""));SetWindowText(hEditRes2, TEXT(""));SetWindowText(hEditRes3, TEXT(""));EnableWindow(hButtonCalc, TRUE);}
}INT_PTR CALLBACK DialogProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{UNREFERENCED_PARAMETER(lParam);switch (uMsg){case WM_INITDIALOG:{HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON));SendMessage(hWndDlg, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);SendMessage(hWndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);hEditA = GetDlgItem(hWndDlg, IDC_EDIT_A);hEditB = GetDlgItem(hWndDlg, IDC_EDIT_B);hEditN = GetDlgItem(hWndDlg, IDC_EDIT_N);HWND hCheckBorrow = GetDlgItem(hWndDlg, IDC_CHECK_BORROW);hButtonCalc = GetDlgItem(hWndDlg, IDC_BUTTON_CALC);hEditRes1 = GetDlgItem(hWndDlg, IDC_EDIT_RES1);hEditRes2 = GetDlgItem(hWndDlg, IDC_EDIT_RES2);hEditRes3 = GetDlgItem(hWndDlg, IDC_EDIT_RES3);SetWindowText(hEditA, TEXT("3"));SendMessage(hEditA, EM_SETLIMITTEXT, (WPARAM)INPUT_LIMIT, (LPARAM)0);SetWindowText(hEditB, TEXT("1"));SendMessage(hEditB, EM_SETLIMITTEXT, (WPARAM)INPUT_LIMIT, (LPARAM)0);SetWindowText(hEditN, TEXT("18"));SendMessage(hEditN, EM_SETLIMITTEXT, (WPARAM)INPUT_LIMIT, (LPARAM)0);SendMessage(hCheckBorrow, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);return (INT_PTR)TRUE;}break;case WM_COMMAND:{switch (wParam){case MAKEWPARAM(IDCANCEL, BN_CLICKED):{EndDialog(hWndDlg, (INT_PTR)0);return (INT_PTR)TRUE;}break;case MAKEWPARAM(IDC_EDIT_A, EN_CHANGE):{ClearResults();return (INT_PTR)TRUE;}break;case MAKEWPARAM(IDC_EDIT_B, EN_CHANGE):{ClearResults();return (INT_PTR)TRUE;}break;case MAKEWPARAM(IDC_EDIT_N, EN_CHANGE):{ClearResults();return (INT_PTR)TRUE;}break;case MAKEWPARAM(IDC_CHECK_BORROW, BN_CLICKED):{ClearResults();return (INT_PTR)TRUE;}break;case MAKEWPARAM(IDC_BUTTON_CALC, BN_CLICKED): //计算部分{if (GetWindowTextLength(hEditA) <= 0){MessageBox(hWndDlg, TEXT("未输入起换空瓶数(a)!"), TEXT("错误"), MB_OK | MB_ICONHAND);SetFocus(hEditA);return (INT_PTR)TRUE;}if (GetWindowTextLength(hEditB) <= 0){MessageBox(hWndDlg, TEXT("未输入可换啤酒数(b)!"), TEXT("错误"), MB_OK | MB_ICONHAND);SetFocus(hEditB);return (INT_PTR)TRUE;}if (GetWindowTextLength(hEditN) <= 0){MessageBox(hWndDlg, TEXT("未输入购买啤酒数(n)!"), TEXT("错误"), MB_OK | MB_ICONHAND);SetFocus(hEditN);return (INT_PTR)TRUE;}UINT a = GetDlgItemInt(hWndDlg, IDC_EDIT_A, NULL, FALSE);if (!a){MessageBox(hWndDlg, TEXT("起换空瓶数(a)应大于0!"), TEXT("错误"), MB_OK | MB_ICONHAND);SendMessage(hEditA, EM_SETSEL, (WPARAM)0, (LPARAM)-1);SetFocus(hEditA);return (INT_PTR)TRUE;}UINT b = GetDlgItemInt(hWndDlg, IDC_EDIT_B, NULL, FALSE);if (b >= a){MessageBox(hWndDlg, TEXT("可换啤酒数(b)应小于起换空瓶数(a)!"), TEXT("错误"), MB_OK | MB_ICONHAND);SendMessage(hEditB, EM_SETSEL, (WPARAM)0, (LPARAM)-1);SetFocus(hEditB);return (INT_PTR)TRUE;}UINT n = GetDlgItemInt(hWndDlg, IDC_EDIT_N, NULL, FALSE);UINT u1, u2, u3;if (IsDlgButtonChecked(hWndDlg, IDC_CHECK_BORROW) == BST_UNCHECKED){if (n < b)b = n;u1 = (n - b) / (a - b);u2 = (n - b) % (a - b);u3 = b;}else{u1 = n / (a - b);u2 = n % (a - b);u3 = 0U;}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()
{{INITCOMMONCONTROLSEX InitCtrls;InitCtrls.dwSize = (DWORD)sizeof(INITCOMMONCONTROLSEX);InitCtrls.dwICC = ICC_WIN95_CLASSES;InitCommonControlsEx(&InitCtrls);}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瓶,一般人是该满意了哈~
经典数学问题“空瓶换酒”求解(C/C++)相关推荐
- Python3多思路解决空瓶换酒问题
思路导航 前言 一.一行代码 二.迭代求解 三.递归求解 总结 前言 空瓶换酒是一类很经典的智力趣题,也有很多不同的问题版本.本文旨在小结其解决方法,以加深理解. 空瓶换酒的目标是求解最终能喝 ...
- 酒瓶换酒编程C语言,巧用公式速解“空瓶换酒”问题
近年来,公务员考试数学运算部分出题形式越来越灵活,题型方面以极值问题.统筹问题.空瓶换酒等问题为代表.下面广西公务员考试网重点讲解一下"空瓶换酒"的解法. [真题精选]12个啤酒空 ...
- Python入门:从空瓶换酒聊起
Python入门:从空瓶换酒聊起 最近在学习Python的过程中,发现了一道有趣的编程题目--空瓶换酒.这个问题是这样描述的:假设你有m个空瓶子,可以用其中n个空瓶子换一瓶酒.那么,你最终最多能喝到多 ...
- 空瓶换酒问题【一行代码】
[问题] 已知:N个空瓶可以换 1 瓶酒, 问:若小明买m瓶,那么他最终可以喝到几瓶? [声明] N为大于 1 的自然数,否则结果为无穷. 不考虑借空瓶的行为. 空瓶换酒问题简单易懂,可以算是学习编程 ...
- 【算法基础】空瓶换酒
文章目录 空瓶换酒-python实现 1.算法分析 1.1 通常情况 1.2 赊账情况 空瓶换酒-python实现 最近学习学习到一种空瓶换酒的算法,其题目描述为:假设一瓶啤酒2元钱,商家为了促销,规 ...
- java编写换酒问题,空瓶换酒问题
例:某商店出售啤酒,规定每5个空啤酒瓶能换1瓶啤酒.张叔叔家买了80瓶啤酒,喝完后再按规定用空啤酒瓶去换啤酒,那么他们家前后共能喝到多少瓶啤酒? 分析与解:我们按照实际换酒过程分析: 喝掉80瓶啤酒, ...
- java编写换酒问题,ASP空瓶换酒递归算法题目
今天有个朋友问我一个小学生的奥数题,酒1元钱1瓶,2个空瓶子可以换一瓶酒,问20块钱可以喝多少瓶酒.我OUT了,我被鄙视了. 我不会,但是谁让我是写代码的呢,写了个小程序用来鄙视他.告诉他,我不仅知道 ...
- #1518空瓶换酒问题
一.题目 难度:简单 小区便利店正在促销,用 numExchange 个空酒瓶可以兑换一瓶新酒.你购入了 numBottles 瓶酒. 如果喝掉了酒瓶中的酒,那么酒瓶就会变成空的. 请你计算 最多 能 ...
- python巧妙解决空瓶换酒问题
问题: 某超市促销,举办空酒瓶和酒瓶盖换酒活动,规定 2 个空瓶或 4 个瓶盖可换一瓶酒.若小明最开始买了 n 瓶酒,则他总共能喝到多少瓶酒? 思路: 如果瓶子数大于2或盖子数大于4就可以换一瓶酒,而 ...
最新文章
- OpsDev是什么?
- 用bash命令得到Windows一个目录下的所有文件并且把结果输入到一个文件
- 华为认证数通专家HCIE-Datacom 11月30日发布
- java commons.util_Java — CommonUtil
- 昇腾AI计算,无惧618冲动消费
- oracle 9i手动启动数据库,Oracle9iAS (之五): 手工起动,关闭系统
- javaSE-基础篇-经典赋值:两变量值的交换
- 解决hibernate只能插入一条数据的问题
- Mysql ORDER BY用法的一点理解
- C语言水平镜像处理16色位图,C语言使用HZK16显示每个像素的代码
- 集成电路那些事儿:CMOS模拟集成电路版图基础
- Mac OS 下的Vim使用系统剪切板
- 图像质量评估指标(3) 特征相似度FSIM
- Android系统之制作开机LOGO
- VHDL——含异步清零和同步使能的加法计数器源程序
- c语言扇形打印图片,圆形CD绘制 (扇形)
- #发现你#小说的交互——交互故事性
- 子矩阵的和(Python实现)
- 编程语言之时下潮流与实用价值
- 图片如何添加水印文字?如何设置照片水印?