数值算法入门-求4轮车 3轮车 2轮车的分配问题的最优解

来源:互联网 发布:仓禀实而知礼节 编辑:程序博客网 时间:2024/05/01 19:14
[简介]
常用网名: 猪头三
出生日期: 1981.XX.XX
个人网站: http://www.x86asm.com
QQ交流:  643439947
编程生涯: 2001年~至今[14年]
职业生涯: 12年
开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python
开发工具: Visual Studio、Delphi、XCode、Eclipse
技能种类: 逆向 驱动 磁盘 文件
研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全
项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测

[序言]
前段几天, 有个家伙整天跟我吹这个道题目:"有16辆车子, 一共45个轮子, 请问4轮车, 3轮车, 2轮车分别是几辆?", 他第一次解这个题目号称只用5分钟, 我直接说他吹牛B.

[我第一次解这个题目耗时多少?]
首先声明, 我从事编程领域相关的, 快15年了. 在这十多年的时间里, 我从来没做过任何一道数值算法的题目包括实际项目开发中也没用过数值算法的相关理论. 这次算是第一次了, 从思考到编码到程序成功运行, 我一共耗时30分钟来处理. 因此广大的编程朋友, 自己对号入座看看自己需要多少时间哦. 

[最优解]
什么是最优解, 你只要包含如下2个标准就可以了.
1> 把实际问题转换为最简单最有效的数学公式
2> 基于最简单最有效的数学公式, 转换为最高效率的代码来进行求解


[请放松压力]
数值算法理论的应用, 大多数编程领域是用不到的, 如果这道题目你们无法做出最优解, 也没什么关系, 不会影响编程就业. 但如果能做出最优解, 那说明你是一个具有数学素养的程序员, 一般这类程序员优势还是比较明显的.

[解题的思路是多样性的]
当我在QQ说说公布这个题目时候, 没想到有那么多朋友来参与, 这让我看到了不同的解题思维, 有古板的, 有常规的, 有另类的... 但不管如何, 大多数朋友都能解出答案, 但到底是不是最优呢? 我相信你们看到我下面的推导, 自己应该心里有个底了.

[开始解题:有16辆车子, 一共45个轮子, 请问4轮车, 3轮车, 2轮车分别是几辆? ]
1> 由题目可以得出如下三元二次方程组
A => X + Y + Z = 16
B => 4X + 3Y + 2Z = 45 

其中: X 表示 4轮车 Y 表示 3轮车 Z表示 2轮车

2> 利用消元方式, 找到最优的 "X与Y的关系" 或者 "X与Z的关系" 或者 "Y与Z的关系"
2.1.1> "X与Y的关系" 如下:
B-2A = 45 - 32 = 4X + 3Y + 2Z - 2X + 2Y + 2Z 推导出 13 = 2X + Y 再推导出 2X = 13 - Y 由此可得X Y的范围: 0 <= X <= 6 , 0 <= Y <= 13
2.1.2> "X与Z的关系" 如下:
3A-B = 48 - 45 = 3X + 3Y + 3Z - 4X -3Y - 2Z 推导出 3 = -X - Z 再推导出 X = -(3 + Z) 由于车辆数目不能为负数, 因此 "X与Z的关系" 不存在合理的关系, 可作废.
2.1.3> "Y与Z的关系" 如下:
4A - B = 64 - 45 = 4X + 4Y + 4Z - 4X - 3Y - 2Z 推导出 Y + 2Z = 19 在推导出 2Z = 19 - Y  由此可得 Y Z的范围: 0 <= Z <= 9 , 0 <= Y <= 16
由上面的 2.1.1 、2.1.2 、2.1.3 可知, X的取值范围最小, 那就意味着如果要通过X来计算出Y或者Z的值时, 只需要进行6次求解, 就可以了, 因此优先消元Z.

2.2> 其实要确定最优的关系, 还有另一种方式, 就是求 X Y Z 的最大范围:
比如:
2.2.1 > 假设 X=0 Y=0 那么根据16辆车和45个轮子可以得出  0 <= Z <= 22 但由于最多只有16辆车, 因此范围调整为 0 <= Z <= 16
2.2.2 > 假设 X=0 Z=0 那么根据16辆车和45个轮子可以得出  0 <= Y <= 15
2.2.3 > 假设 Y=0 Z=0 那么根据16辆车和45个轮子可以得出  0 <= X <= 11
由上面的 2.1.1 、 2.1.2 、2.1.3 可知, Z的取值范围最大, 那就意味着如果要通过Z来计算出X或者Y的值时, 需要进行16次的求解, 效率最低. 因此Z首先需要消元.

[开始把推导出来的数学公式转换为代码]
声明: 这个代码是C#代码, 我懒得用C/C++写了.


[还有比我更优秀的代码, 由网友"二律背反"原创并分享 如下: ]
声明: 这个代码是C代码


[结束语]
通过这次小小的探讨, 希望大家明白一件事情: 数值算法 是一个非常高深的领域, 上面的题目只是数值算法的一个简单的科普, 大家记住我说的2个原则来进行数值算法研究即可:
1> 把实际问题转换为最简单最有效的数学公式
2> 基于最简单最有效的数学公式, 转换为最高效率的代码来进行求解

0 0
原创粉丝点击