buaaoo_first_improvement
优化,还是不优化,这是个问题
本讨论仅基于程序基本上正确的情况下。
(一)第一次作业
众所周知,本次作业没有优化到100分的都进入了B组或者C组,所以事实上本次作业的优化是十分简单的,在这里提几句。
(1)合并同类项
最简单的做法也是最高效的做法,通过Hashmap,将指数存为key,将系数作为对应value,那么可以很简单的将同类项进行合并。
(2)对项进行省略
当然,+0,0*,1*,等这样无意义的项,仅需要做特殊判断,那么就可以直接省略,从而缩减表达式的长度。
(3)对项进行排序
对于负数,会比正数多一个不必要的符号,所以我们可以直接将负号作为减号放到项中,所以最好的做法是对所有在Hashmap里的系数做一个判断,先输出正项,若无正项,则输出负项。
经过以上三种处理,第一次作业便可以完美的将表达式化简为最简形式。
(二)第二次作业
本部分是本次讨论的重点部分。
第二次作业开始,大家的算法实现就变得五花八门,面向过程的,面向对象的,不一而足。
所以在这里我要基于一个看起来似乎是解决本次作业最好的算法来讨论化简。
根据题目可以得知,每一个原子项可以写成如下形式(请原谅我的超长正则):
(([+-]{0,3}\\d+)|([+-]{0,2}x(\\^[+-]?\\d+)?)|([+-]{0,2}sin\\(x\\)(\\^[+-]?\\d+)?)|([+-]{0,2}cos\\(x\\)(\\^[+-]?\\d+)?))(\\*(([+-]?\\d+)|(x(\\^[+-]?\\d+)?)|(sin\\(x\\)(\\^[+-]?\\d+)?)|(cos\\(x\\)(\\^[+-]?\\d+)?)))*
所以首先应该做的是对于原子项中的因子合并,从而形成形如a*x^b*sin(x)^c*cos(x)^d的形式,进而大大缩短了处理难度,下面放出我的合并函数:
for (String it : ob) {
if (it.matches("[+\\-]?\\d+")) {
num = num.multiply(new BigInteger(it));
}
else if (it.matches("[+-]?sin\\(x\\)(\\^[+-]?\\d+)?")) {
if (it.substring(0, 1).matches("-")) {
num = num.multiply(new BigInteger("-1"));
}
sin = "sin(x)^" + combine(sin, it);
}
else if (it.matches("[+-]?cos\\(x\\)(\\^[+-]?\\d+)?")) {
if (it.substring(0, 1).matches("-")) {
num = num.multiply(new BigInteger("-1"));
}
cos = "cos(x)^" + combine(cos, it);
}
else if (it.matches("[+-]?x(\\^[+-]?\\d+)?")) {
if (it.substring(0, 1).matches("-")) {
num = num.multiply(new BigInteger("-1"));
}
x = "x^" + combine(x, it);
}
}
private String combine(String sss, String it) {
Pattern p = Pattern.compile("\\^");
Matcher m = p.matcher(it);
BigInteger b1;
BigInteger b2;
if (sss.equals("")) {
if (m.find()) {
String t = it.substring(m.start() + 1);
return t;
}
else {
return "1";
}
}
else {
Pattern pp = Pattern.compile("\\^");
Matcher mm = pp.matcher(sss);
if (mm.find()) {
b1 = new BigInteger(sss.substring(mm.start() + 1));
if (m.find()) {
b2 = new BigInteger(it.substring(m.start() + 1));
}
else {
b2 = new BigInteger("1");
}
b1 = b1.add(b2);
return b1.toString();
}
}
return "0";
}
便将每一原子项中的同类因子合并,之后应该在项内做排序,从而得出如上述规范化的式子,即a*x^b*sin(x)^c*cos(x)^d的形式,这里就省略排序代码。
将通过+-分隔的每一原子项按照如上规则处理好之后,可以进行存入Hashmap处理,处理方式如下:
设立Poly类,其中包含BigInteger参数三个,分别为b、c、d,即x,sin(x),cos(x)各自的指数(若不存在此因子则指数为0),那么可以将此三元组作为key值,将a,即系数作为value,形成一个新的Hashmap,形式为Hashmap<Poly, BigInteger>,可知,对每个相同形式的项,均可以用前述方法处理并合并为同类项。
对于三角函数化简公式,比较简单的有如下几种:
sin(x)^2 + cos(x)^2 = 1
1 - cos(x)^2 = sin(x)^2
1 - sin(x)^2 = cos(x)^2
进阶版的有如下形式:
sin(x)^4 + 2 * sin(x) ^2* cos(x)^2 + cos(x)^4 = 1
sin(x)^4 - cos(x)^4 = sin(x)^2 - cos(x)^2
......
事实上,若想比较好的化简,应该先将进阶版部分的三角函数进行化简(即降次,否则会导致需要重复使用基础版化简公式,导致TLE)
由于我们的存储方式,可以知道,对于进阶版化简部分,可以枚举出几个典型的公式,进行if-else判断(方法繁琐但不容易出错),将常见的进阶版公式化简之后,就可以愉快的开始基础版化简了。
· 而根据我们之前所讨论的Hashmap存储方法,可知两对三元组为<b1, c1, d2>、<b2, c2, d2>,若满足:
1.b1 == b2
2.(abs(c1 - c2) == 2 && d1 == d2) || (abs(d2 - d1) == 2 && c1 == c2)
或
3.b1 == b2
2.(c1 - c2 == 2 && d1 - d2 == -2) || (d2 - d1 == 2 && c1 - c2 == -2)
即可将含有基础版化简形式的部分项化简,若分别考虑两者系数a1, a2,则会保留下某一三元组的部分式子。而上述基础版化简的时候要记得用if-else判断为哪种形式,否则化简出来的式子会含有^0之类不应该存在的部分。
在化简的时候需要注意的是,在Hashmap存化简之后的项的时候,要用keycontains检测是否已经存在了项,不要将已有的项覆盖掉:)
最后处理按照第一次作业类似的方法(排序,正项提前等)即可将化简做到比较好的程度。
(三)第三次作业
具体请见作业博客,网址如下:
https://www.cnblogs.com/dxy1999/p/10585219.html
最后, 我想说,其实化简表达式并不完全是为了分数,而更应该从中学到如何将OO课程学的更好。试问,如果在化简的时候对于自己的类的概念不清晰,又怎能写出正确的代码呢?疯狂面向过程写代码,又会创造出多么长的代码呢?愿我们共勉。
简,你化不化,它就在那里
buaaoo_first_improvement的更多相关文章
随机推荐
- python将PNG格式的图片转化成为jpg
""" 先来说一下jpg图片和png图片的区别 jpg格式:是有损图片压缩类型,可用最少的磁盘空间得到较好的图像质量 png格式:不是压缩性,能保存透明等图 " ...
- 【LOJ#2402】[THUPC2017]天天爱射击(整体二分)
[LOJ#2402][THUPC2017]天天爱射击(整体二分) 题面 LOJ 题解 显然对于每块木板可以二分被打烂的时间. 那么直接上整体二分处理就行了. #include<iostream& ...
- 商誉专题RN及H5项目总结
React(基础框架): React 是基础框架,是一套基础设计实现理念,开发者不能直接使用它来开发移动应用或者网页. React.js(web网页开发):在React框架之上,发展出了React.j ...
- python第十一天
今日内容 1. 函数的参数 2. 函数对象 -- 函数名 * * * *重点! 3. 函数 的嵌套调用 1. 形参与实参: 函数介绍: 1.1 函数为什么要有参数: 因为内部的函数体需要外部的数据 ...
- thinkphp 5.0 在appache下隐藏index.php入口代码
一.在appache的配置文件httpd.conf中开启rewrite_module 二.启用.htaccess的配置 启用.htaccess,需要修改httpd.conf,启用AllowOverri ...
- vue-cli 项目踩坑 npm install 时出错
1.报错如下: 2.此时你执行npm run dev / npm run build 会报错如下 npm ERR! code ELIFECYCLEnpm ERR! errno 1npm ERR! v ...
- 浅议极大似然估计(MLE)背后的思想原理
1. 概率思想与归纳思想 0x1:归纳推理思想 所谓归纳推理思想,即是由某类事物的部分对象具有某些特征,推出该类事物的全部对象都具有这些特征的推理.抽象地来说,由个别事实概括出一般结论的推理称为归纳推 ...
- APICloud学习第二天——操作云数据库
//连接apicloud云数据库 var model=api.require('model'); model.config({ appId: 'A6008558346855', appKey: '60 ...
- QPS从0到4000请求每秒,谈达达后台架构演化之路
达达是全国领先的最后三公里物流配送平台. 达达的业务模式与滴滴以及Uber很相似,以众包的方式利用社会闲散人力资源,解决O2O最后三公里即时性配送难题(目前达达已经与京东到家合并). 达达业务主要包含 ...
- react native头部标题样式修改
navigationOptions: ({navigation}) => ({ headerTitle:'评估记录', headerBackTitle:null, headerLeft:null ...