初学者编程编程实战指南 (3)- 性能优化

百马百担问题

题目描述

百马百担问题。有100匹马,驮100担货,大马驮3担,中马驮2担,两匹小马1担,编程计算所有可能的驮法?

输入

输出

输出所有可能的驮法。

每行输出一种驮法,每种驮法依次输出:

     大马数,中马数,小马数

如2,30,68
表示大马数为2,中马数为30,小马数为68

样例输入

样例输出

2,30,68

5,25,70

8,20,72

11,15,74

14,10,76

17,5,78

20,0,80

下面的初学者容易写出的代码,而且最常犯错的地方就是忘记 z % 2 == 0

 1 #include <stdio.h>
 2
 3 int main(void)
 4 {
 5     int x, y, z;
 6     for(x = 0; x <= 33; x++)
 7         for(y = 0; y <= 50; y++)
 8             for(z = 0; z <= 100; z++) {
 9                 if(x + y + z == 100 && 3 * x + 2 * y + z / 2 == 100 && z % 2 == 0)
10                     printf("%d,%d,%d\n", x, y, z);
11             }
12
13     return 0;
14 }

能不能去掉z % 2 == 0这个条件呢? 一种思路就是将 3 * x + 2 * y + z / 2 == 100两边都乘以2,等式成为6*x+4*y+z==200。 更好的做法是修改循环变量的步长

 1 #include <stdio.h>
 2
 3 int main(void)
 4 {
 5     int x, y, z;
 6     for(x = 0; x <= 33; x++)
 7         for(y = 0; y <= 50; y++)
 8             for(z = 0; z <= 100; z += 2) {
 9                 if(x + y + z == 100 && 3 * x + 2 * y + z / 2 == 100)
10                     printf("%d,%d,%d\n", x, y, z);
11             }
12
13     return 0;
14 }

如果进一步观察,发现第8行的枚举z是没有必要的,因为z必然是100-x-y,这样会节省不少开销。

 1 #include <stdio.h>
 2
 3 int main(void)
 4 {
 5     int x, y, z;
 6     for(x = 0; x <= 33; x++)
 7         for(y = 0; y <= 50; y++) {
 8             z = 100 - x - y;
 9             if(z % 2 == 0 && 3 * x + 2 * y + z / 2 == 100)
10                 printf("%d,%d,%d\n", x, y, z);
11         }
12
13     return 0;
14 }

变化一下判断条件,可以用100-x-y代替z,从而抹去z的痕迹。 6x+4y+z = 100+5x+3y,有下面第8行的判等式(该式实际一开始就可以推出),这个式子是推导的结果,绝非一眼所能看出。

 1 #include <stdio.h>
 2
 3 int main(void)
 4 {
 5     int x, y;
 6     for(x = 0; x <= 33; x++)
 7         for(y = 0; y <= 50; y++) {
 8             if(5 * x + 3 * y  == 100)
 9                 printf("%d,%d,%d\n", x, y, 100 - x - y);
10         }
11
12     return 0;
13 }

有了第8行,可看出x不超过20,而且y也不必枚举了。程序只剩一层循环,得到了极大的优化。

 1 #include <stdio.h>
 2
 3 int main(void)
 4 {
 5     int x, y;
 6     for(x = 0; x <= 20; x++){
 7         y = 100 - 5 * x;
 8         if(y % 3 == 0){
 9             y /= 3;
10             printf("%d,%d,%d\n", x, y, 100 - x - y);
11         }
12     }
13
14     return 0;
15 }

在本例中,我们通过步步优化,从三层循环简化到一层循环,执行效率是提高了,但是代码的可读性却是大大下降了。对于小程序来讲,可读性更重要一些。但是在一些性能关键的地方,优化是必不可少的。

时间: 2025-01-01 12:34:46

初学者编程编程实战指南 (3)- 性能优化的相关文章

性能优化指南:性能优化的一般性原则与方法

作为一个程序员,性能优化是常有的事情,不管是桌面应用还是web应用,不管是前端还是后端,不管是单点应用还是分布式系统.本文从以下几个方面来思考这个问题:性能优化的一般性原则,性能优化的层次,性能优化的通用方法.本文不限于任何语言.框架,不过可能会用Python语言来举例. 不过囿于个人经验,可能更多的是从Linux服务端的角度来思考这些问题. 本文地址:http://www.cnblogs.com/xybaby/p/9055734.html 一般性原则 依据数据而不是凭空猜测 这是性能优化的第一

iOS开发——项目实战总结&amp;UITableView性能优化与卡顿问题

UITableView性能优化与卡顿问题 1.最常用的就是cell的重用, 注册重用标识符 如果不重用cell时,每当一个cell显示到屏幕上时,就会重新创建一个新的cell 如果有很多数据的时候,就会堆积很多cell.如果重用cell,为cell创建一个ID 每当需要显示cell 的时候,都会先去缓冲池中寻找可循环利用的cell,如果没有再重新创建cell 2.避免cell的重新布局 cell的布局填充等操作 比较耗时,一般创建时就布局好 如可以将cell单独放到一个自定义类,初始化时就布局好

Linux性能优化实战: Linux 性能优化答疑(四)(32)

一.上节总结 专栏更新至今,四大基础模块的第三个模块——文件系统和磁盘 I/O 篇,我们就已经学完了.很开心你还没有掉队,仍然在积极学习思考和实践操作,并且热情地留言与讨论. 今天是性能优化的第四期.照例,我从 I/O 模块的留言中摘出了一些典型问题,作为今天的答疑内容,集中回复.同样的,为了便于你学习理解,它们并不是严格按照文章顺序排列的. 每个问题,我都附上了留言区提问的截屏.如果你需要回顾内容原文,可以扫描每个问题右下方的二维码查看. 二.问题 1:阻塞.非阻塞 I/O 与同步.异步 I/

Java多线程编程模式实战指南之Promise模式

Promise模式简介(转) Promise模式是一种异步编程模式 .它使得我们可以先开始一个任务的执行,并得到一个用于获取该任务执行结果的凭据对象,而不必等待该任务执行完毕就可以继续执行其他操作.等到我们需要该任务的执行结果时,再调用凭据对象的相关方法来获取.这样就避免了不必要的等待,增加了系统的并发性.这好比我们去小吃店,同时点了鸭血粉丝汤和生煎包.当我们点餐付完款后,我们拿到手的其实只是一张可借以换取相应食品的收银小票(凭据对象)而已,而不是对应的实物.由于鸭血粉丝汤可以较快制作好,故我们

Java多线程编程模式实战指南(三):Two-phase Termination模式--转载

本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-two-phase-termination.转载请注明作者: 黄文海 出处:http://viscent.iteye.com. 停止线程是一个目标简单而实现却不那么简单的任务.首先,Java没有提供直接的API用于停止线程.此外,停止线程时还有一些额外的细节需要考虑,如待停止的线程处于阻塞(等待锁)或者等待状态(等待其它

Java多线程编程模式实战指南(二):Immutable Object模式--转载

本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-immutable-object.转载请注明作者: 黄文海 出处:http://viscent.iteye.com. 多线程共享变量的情况下,为了保证数据一致性,往往需要对这些变量的访问进行加锁.而锁本身又会带来一些问题和开销.Immutable Object模式使得我们可以在不使用锁的情况下,既保证共享变量访问的线程安

Java多线程编程模式实战指南(一):Active Object模式--转载

本文由黄文海首次发布在infoq中文站上:http://www.infoq.com/cn/articles/Java-multithreaded-programming-mode-active-object-part1 .转载请注明作者: 黄文海 出处:http://viscent.iteye.com. Active Object模式简介 Active Object模式是一种异步编程模式.它通过对方法的调用与方法的执行进行解耦来提高并发性.若以任务的概念来说,Active Object模式的核心

Java多线程编程模式实战指南(三):Two-phase Termination模式

停止线程是一个目标简单而实现却不那么简单的任务.首先,Java没有提供直接的API用于停止线程.此外,停止线程时还有一些额外的细节需要考虑,如待停止的线程处于阻塞(等待锁)或者等待状态(等待其它线程).尚有未处理完的任务等.本文介绍的Two-phase Termination模式提供了一种通用的用于优雅地停止线程的方法. Two-phase Termination模式简介 Java并没有提供直接的API用于停止线程.Two-phase Termination模式通过将停止线程这个动作分解为准备阶

Java多线程编程模式实战指南一:Active Object模式(上)

Active Object模式简介 Active Object模式是一种异步编程模式.它通过对方法的调用与方法的执行进行解耦来提高并发性.若以任务的概念来说,Active Object模式的核心则是它允许任务的提交(相当于对异步方法的调用)和任务的执行(相当于异步方法的真正执行)分离.这有点类似于System.gc()这个方法:客户端代码调用完gc()后,一个进行垃圾回收的任务被提交,但此时JVM并不一定进行了垃圾回收,而可能是在gc()方法调用返回后的某段时间才开始执行任务--回收垃圾.我们知