hdu 1003 解题报告 ---- Max Sum
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1003
#include <stdio.h> #include <string.h> int main(){ int m,n,k,temp; int start,end,max,sum,x,i; scanf("%d",&n); k=0; while(k++<n){ max=-100000; sum=0; temp=1; scanf("%d",&m); for (i=0;i<m;i++){ scanf("%d",&x); sum+=x; if(sum>=max){ max=sum; start=temp; end=i+1;//end坐标为目前最后一个坐标 } if(sum<0){ sum=0;//若逐渐递减到0了,则sum清零,并且改变下次启示坐标为i+2 temp=i+2;//下次改变max值时的start坐标 } } printf("Case %d:\n%d %d %d\n",k,max,start,end); if(k<n) printf("\n"); } return 0; }
代码中两个if判断:
(1)若当前序列之和sum大于max,则改变end坐标为当前坐标,max=sum
(2)若sum<0,则丢弃,启示节点下次将会变成当前的下一个元素,结论:
1、现有大部分Mac配置了i7处理器,应设置并发任务数量为8,可以达到最佳效果
2、4G内存及8G内存下,编译时间是基本一样的,故无需升级内存,但需要保持构建机器尽量少地打开不相关的程序(例如打开N个XCODE),同时每隔一段时间可以重启下机器
一、环境
操作系统:Mac OS x 10.7.4
内存:4GB 1333MHZ DDR3 ;8GB 1333MHZ
处理器:2GHz Intel Core i7
被测项目: 项目 代码文件大小 A 68.4MB B 472MB C 1044MB
表一 4G内存下设置不同并发任务(2、4、6、8分别表示并发任务为2、4、6、8)
表二 4G内存下设置不同并发任务
表三:4G、8G内存的编译时间对比
三、分析
关于并发数量任务设置:
目前xcode默认设置的并发任务数量为4(网上说默认为2,但我们现在的xcode版本估计已经优化了这一设置,默认为4),可以看到当设置并发任务为4时,比设置为2要快40%左右。而事实上,i7是一款支持超线程技术的四核处理器,相当于是有8个处理核心,因此,将并发数量设为8时,可以提高效率,相比并发数量为4时,可以快13%左右
关于内存大小对编译的影响:
由表三可以看到,在重新启动机器后,再进行构建,内存4G、8G下的编译时间基本是一样的;另外,需要注意到,且需要持续观察的一个现象是:1 测试机器之前是作为普通的构建机器,每天需要执行大量的构建任务,一开始未对其进行重启便开始测试,这时候的编译时间要比重启后再进行测试的耗时,要多20%左右(数据见附件);2. 4G内存下,其可用内存一直在1G到200MB之间波动,而8G内存下,可用内存一般都在4G以上;据这两个现象,可以初步推断,4G内存会随着机器执行任务次数的增多而逐渐消耗,到最后,也会成为性能的瓶颈,因此,我们不要在构建机器上打开不相关的程序,且可以定期重启机器
关于构建文件的缓存
对同个任务,第一次构建的耗时要比第二次构建的耗时要长。这是因为,在第一次构建后,在内存或者虚拟内存中,会缓存上一次构建的文件;因此第二次构建的io耗时就减少了;过程中也测试了,重新启动机器后再进行构建(这时候就没有了缓存),并发任务数量设为8,依然要比并发数量设为4快12%左右(和不重启机器的结论是一样的)。
其他:
1. 并发任务数量相关命令(在终端运行以下命令,就能永久生效,不用每次编译都运行)
获取现有设置:
defaults read com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks
设置并发任务数量为8:
defaults write com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks 8
一、自封装字段
1、直接访问一个字段,方便,容易阅读,但是字段之间的耦合关系会越来越紧密,所以可以为这个字段建立取值/设置函数,并且只以这些函数来访问这些字段。
2、利用函数来访问字段,相当于增加了一个中间层,修改的时候方便。
二、以对象取代数据值
1、如果一个数据项需要与其他的数据和行为在一起使用才有意思,那么可以将数据项变成对象。
2、将数据和行为封装在一起就是面向对象的本质。
三、将值对象改变为引用对象
1、如果一个类拥有许多个相等的实例,那么可以将这个值对象变成引用对象,这样整个系统中就只有一个副本了,减少了内存的浪费。
2、一个需要注意的地方,利用工厂方法接管类的构造函数,并且将构造函数设置为私有,由你来控制实例的产生。
四、将引用对象改为值对象
1、如果一个引用对象很小(占内存小)不可变,并且不易管理,可以将它变为一个值对象。
2、不可变的对象是只对象本身不能改变,但是可以改变对象之间的关系,即可以重新生成一个对象替换另一个对象。
五、以对象取代数组
1、如果一个数组,其中数组元素各自代表不同的东西,可以用对象替代数组,对于数组中的每一个元素,以一个字段来表示。
2、数组的本质是以某种顺序容纳一组相似对象,如果违反规则使用数组,那么就应该将它重构成数组。
六、复制被监视数据
1、如果有一些数据置于GUI控件中,而逻辑层函数需要访问这些数据,应该利用观察者模式将数据复制到逻辑层函数中,而不是在GUI中处理;
2、一个系统的设计一定要有良好的分层设计,这样耦合性才会低,并且逻辑才会清晰并且容易修改;
3、观察者模式的合理运行是解藕的利器。
七、将单向关联改为双向关联
1、如果两个类都需要对方的特性,但其间只有一条单向连接,那么可以添加一个反向指针,并且修改改变双方关系的函数使能够同时更新两条连接;
2、这个重构方法的关系是在修改双方关系的时候维护关系的改变的一致性。
八、将双向关联改为单向关联
1、如果两个类之间有双向关联,但是其中一个类如今不再需要另一个类的特性的时候,应该去掉不必要的联系;
2、双向关联会增加类之间的耦合性,在不必要的时候一定要去掉;
3、修改之前一定要评估可行性;
九、以字面常量取代魔法数
如果一个字面数值带有特别的含义,创造一个常量,根据其意义为它命名,然后替换之;
十、封装字段
1、尽量不暴露类内部的数据,将数据定义为private,有需要的话可以提供访问函数。
2、它是很多重构手法的第一步。
十一、封装集合
1、如果一个函数访问一个集合的引用,那么可以让这个函数返回集合的值,并在这个类中提供添加/移除集合元素的函数
2、让所有的修改都在类的内部,可以防止意外的修改,对代码可读性和调试都有好处。
十二、以数据类取代记录
如果需要面对传统编程环境中的记录结构,可以为该数据创建一个除取值和设值外没有其他行为的数据对象类。
十三、以类取代类型码
1、如果类中有一个类型码,但是它不影响类的行为,可以用一个新的类替换该数值类型码;
2、在类型码要用于switch时不能采用本条重构,因为C++的switch只能接受int型的参数;
3、本条重构的思想是利用编译器会检查类的类型来实现类型安全。
十四、以子类取代类型码
1、如果类的类型码在一个实例中是不能改变的,但是这个类型码会影响类的行为,那么可以以子类取代这个类型码;
2、然后运行多态取代根据类型码处理的行为;
3、提供构造函数的工厂函数,让switch只在工厂函数中出现。
十五、以state/strategy取代类型码
1、如果类的类型码会影响类的行为,但是它是可变的,因此不能用第十四条重构手法,那么可以以类型对象取代类型码;
2、将于类型对象相关的switch修改为类型对象的多态处理。
十六、以字段取代子类
如果子类的唯一差别只是返回常量数据的函数身上,那么可以修改这些函数,使它们返回父类的一个字段(新增),然后去掉子类。