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的更多相关文章
随机推荐
- 【SEERC2018A】【XSY3319】Numbers
给你一个数 \(n\),求有多少种方案能把 \(n\) 分成两个非零回文数 \((a,b)\) 之和. 两个方案不同当且仅当 \(a_1\neq a_2\). \(n\leq {10}^{18}\) ...
- [BJOI2019]排兵布阵(动态规划)
[BJOI2019]排兵布阵(动态规划) 题面 洛谷 题解 暴力dp: 设\(f[i][j]\)表示考虑到了第\(i\)座城市用了\(j\)人的最大收益,枚举在这个城市用多少人就可以了. 优化: 发现 ...
- Python3 找不到库
import sys sys.path.append('/usr/local/lib64/python3.6/site-packages')sys.path.append('/usr/local/li ...
- 一加3T 误清除data 恢复数据
数据丢失经过:日常用机无备份直接操作:装google框架后,rootexplorer文件浏览器删除多余google应用导致无法开机:开机不成功应该重刷入google gapps包,并没有这样操作而是进 ...
- 浅谈Kubernetes生产架构
注意本文,只是笔者针对Kubernetes生产环境运行的一些关于架构设计和实现方案的总结,内容很粗糙,同时也会不断完善. 首先,我们来梳理下Kubernetes生产架构,其设计适用于绝大多数环境.如下 ...
- python11 函数的定义,调用,分类
## 复习 #一.什么是函数:具体特定功能的代码块 - 特定功能代码块作为一个整体,并给该整体命名,就是函数 # 二.函数的优点:# 1.减少代码的冗余# 2.结构清晰,可读性强# 3.具有复用性,开 ...
- Java IO系列之四:NIO通信模型
分布式rpc框架有很多,比如dubbo,netty,还有很多其他的产品.但他们大部分都是基于nio的, nio是非阻塞的io,那么它的内部机制是怎么实现的呢. 1.由一个专门的线程处理所有IO事件,并 ...
- 深入理解Java的三种工厂模式
一.简单工厂模式 简单工厂的定义:提供一个创建对象实例的功能,而无须关心其具体实现.被创建实例的类型可以是接口.抽象类,也可以是具体的类 实现汽车接口 public interface Car { S ...
- docker学习------记录centos7.5下docker安装更换国内源的处理过程
一.centos7.5下更换阿里源 1.装好centos7.5镜像,将yum源更换为阿里源 第一步:刚出的centos7.5是解析不到阿里的东西的,所以找了台centos7.4,下载一些包 (1) 下 ...
- 微信小程序开发——点击按钮退出小程序的实现
微信小程序官方是没有提供退出的API的,但是在navigator这个组件中,是有退出这个功能的:详情参考官方文档:navigator.示例代码:1 navigator open-type=" ...