1264: 祈雨(Java)
WUSTOJ 1264: 祈雨
Description
在持续了X天的干旱之后,ACM俱乐部决定由LCM去请求雨大师XH祈雨,CMS则准备工具收集雨水,由于ACM俱乐部中有一个逆天的存在,BobLee 他能够用意念用两条线段接水。具体操作如下

现在CMS想要知道BobLee最终能接到多少雨水。(雨水垂直下落,不存在任何偏斜,雨水的多少用面积进行计算)
Input
存在多组输入数据
每组数据两行 (都是整数)
第一行 x1 y1 x2 y2 代表第一条线段的两个端点的坐标
第二行 x3 y3 x4 y4 代表第二条线段的两个端点的坐标
Output
输出BobLee能够接的雨水量 (输出保留两位小数)
Sample Input
0 1 1 0
1 0 2 1
0 1 2 1
1 0 1 2
Sample Output
1.00
0.00
题目分析
题目大意就是用两根线段摆出一个形状,计算最终能接到多少水。下面来看一下接不到水的情况有哪些:
- 当两条线段中至少有一条线段是水平的,那么肯定是接不到水的,结果为
0.00; - 当两条线段是平行的,也是接不到水的,结果为
0.00; - 当两条线段没有交点时,也是接不到水的,结果为
0.00。
当以上三种情况都排除后,说明两条线段有交点。以上只是最简单的排除。但实际上,还有两种情况也是接不到水的。如下图所示:


以上两幅图中,虽然这两条线段不水平而且相交,但是线段A将线段B完全挡住了,雨水都顺着线段A和线段B的右(左)上侧滑走了,根本无法积攒到他们中间的“漏斗”中。因此这种情况结果依然是0.00。
到这里了,只要自己细心一点,代码完全是可以写出来的。如果说上述情况都考虑到了。下面说一些细节问题:
- int型相除结果是不保留小数的,应该都知道。建议此题所有数据均用浮点型,虽然题目说的输入数据是整型的,但是用浮点型更稳妥;
- 有没有分母为零的情况,仔细检查一下;
- 计算面积过程中,计算某些点的坐标,公式有没有写错;
- 上面的最关键的那种接不到水的情况,判断错没错;
- 注意一些相等的地方有没有漏掉。
下面两组我自己的测试数据,算对的数据我就不提供了,毕竟每个人代码都不一样。(代码不同,以下数据仅供参考)
1 1 0 0
0 0 3 2
正确结果:0.25
测试小数,因为我之前用的是int型保存输入数据的,恰好代码中有的地方漏乘了1.0,结果就算成了0.00
1 1 0 0
-2 2 0 0
正确结果:1.00
我之前的代码算成了3.00,原因是一个if-else分支里面的代码错了
如果说你还是找不出来错误,那就只能用最不推荐的办法了——阅读下面这个长达200行的代码了。如有不清楚的地方,请讨论或留言告知本人,我会根据情况稍作修改。
代码
代码有点长,后期会整理代码,按方法讲解 。主要是细节问题。
无语了,我觉得下面代码不怎么好,然后准备重构一下。然鹅,完全重写了两遍,有的地方甚至还优化了,,,奈何(一直被模仿,从未被超越)居然硬生生出现在了我身上,,,后来写的我觉得很对的代码,提交一次没过,心凉了。你们就将就阅读下面这个“烂”(奇葩的是它AC了)代码吧。。。
PS:我自己都不想再看,乐意的话,不懂的地方就直接问我吧。。
另外,我还发现了这个代码有点问题,输入下面这组数据的时候
0 0 0 1
0 0 1 1
正确结果:0.50
但是我自己运行结果:0.00
然而提交代码是正确的。。。所以,OJ测试数据应该没有那种一条线段垂直,一条线段斜着的这种情况。
我已经不想改代码了,毕竟:一直被模仿,从未被超越QAQ
/**
* 用时:274ms
* @author wowpH
* @version A1.0
* @date 2019年4月13日 下午3:32:04
*/
import java.util.Scanner;
public class Main {
private Scanner sc;
// 输入数据,线段端点坐标
private double x1, y1, x2, y2, x3, y3, x4, y4;
private double area; // 面积,也就是接到的雨水
private double intersectionX, intersectionY; // 交点
public Main() {
sc = new Scanner(System.in);
while (sc.hasNext()) {
area = 0; // 初始化接到的雨水为0
input(); // 输入数据
// 两条线都不能水平
if (y1 != y2 && y3 != y4) {
// 两条线段不平行
if (false == parallel()) {
// 两条线段相交
if (intersect()) {
calculate(); // 计算面积
}
}
}
System.out.printf("%.2f\n", area); // 输出接到的雨水
}
sc.close();
}
private void input() {
x1 = sc.nextDouble();
y1 = sc.nextDouble();
x2 = sc.nextDouble();
y2 = sc.nextDouble();
x3 = sc.nextDouble();
y3 = sc.nextDouble();
x4 = sc.nextDouble();
y4 = sc.nextDouble();
}
/**
* @return 两条线段是否平行,是返回true,否返回false
*/
private boolean parallel() {
// 第一条线段垂直
if (x1 == x2) {
// 第二条线段也垂直
if (x3 == x4) {
return true; // 两条都垂直,平行
}
} else { // 第一条不垂直
// 第二条不垂直
if (x3 != x4) {
// 两条都不垂直,计算斜率
double k1, k2;
k1 = (y1 - y2) * 1.0 / (x1 - x2);
k2 = (y3 - y4) * 1.0 / (x3 - x4);
if (k1 == k2) {
return true; // 斜率相同,平行
}
}
}
return false; // 否则不平行
}
/**
* @return 两条线段是否相交,是返回true,否返回false
*/
private boolean intersect() {
double xa = x1 - x2;
double xb = x3 - x4;
double ya = y1 - y2;
double yb = y3 - y4;
double xya = x1 * y2;
double xyb = x2 * y1;
double xyc = x3 * y4;
double xyd = x4 * y3;
double molecule = (xa * (xyc - xyd) - xb * (xya - xyb));
double denominator = (xb * ya - xa * yb);
intersectionX = molecule / denominator; // 相交点x坐标
if (intersectionX < x1 && intersectionX < x2) {
return false; // 相交点X坐标超出第一条线段
} else if (intersectionX > x1 && intersectionX > x2) {
return false; // 相交点X坐标超出第一条线段
} else {
if (intersectionX < x3 && intersectionX < x4) {
return false; // 相交点X坐标超出第二条线段
} else if (intersectionX > x3 && intersectionX > x4) {
return false; // 相交点X坐标超出第二条线段
} else {
intersectionY = ya / xa * intersectionX + (xya - xyb) / xa;
return true;
}
}
}
private void calculate() {
// 分别表示比交点高的线段端点坐标
double pointAX, pointAY, pointBX, pointBY;
if(y1 > intersectionY) {
pointAX = x1;
pointAY = y1;
} else if(y2 > intersectionY) {
pointAX = x2;
pointAY = y2;
} else {
return;
}
if(y3 > intersectionY) {
pointBX = x3;
pointBY = y3;
} else if(y4 > intersectionY) {
pointBX = x4;
pointBY = y4;
} else {
return;
}
double temp;
if(pointAX == pointBX) {
return;
} else if(pointAX > pointBX) {
temp = pointAX;
pointAX = pointBX;
pointBX = temp;
temp = pointAY;
pointAY = pointBY;
pointBY = temp; // 注意别写错
}
double ka, kb;
ka = (pointAY - intersectionY) / (pointAX - intersectionX);
kb = (pointBY - intersectionY) / (pointBX - intersectionX);
if(ka < kb && kb < 0 || ka > 0 && ka < kb) {
return;
}
// 一定能接到雨水
double surfaceIntersectionX, surfaceIntersectionY; // 水面交点
double xa, ya, xya, xyb;
if(pointAY > pointBY) {
surfaceIntersectionY = pointBY;
xa = pointAX - intersectionX;
ya = pointAY - intersectionY;
xya = pointAX * intersectionY;
xyb = pointAY * intersectionX;
surfaceIntersectionX = surfaceIntersectionY * xa / ya - (xya - xyb) / ya;
area = (pointBX - surfaceIntersectionX) * (surfaceIntersectionY - intersectionY) / 2;
} else {
surfaceIntersectionY = pointAY;
xa = pointBX - intersectionX;
ya = pointBY - intersectionY;
xya = pointBX * intersectionY;
xyb = pointBY * intersectionX;
surfaceIntersectionX = surfaceIntersectionY * xa / ya - (xya - xyb) / ya;
area = (surfaceIntersectionX - pointAX) * (surfaceIntersectionY - intersectionY) / 2;
}
}
/**
* @param args
*/
public static void main(String[] args) {
new Main();
}
}
写在最后:
- 如需转载,请于标题下注明链接形式的wowpH的博客即可;
- 代码原创,如需公开引用,不能删除首行注释(作者,版本号,时间等信息)。
1264: 祈雨(Java)的更多相关文章
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- docker部署验证码项目报错:at sun.awt.FontConfiguration.getVersion(FontConfiguration.java:1264)
如果docker部署启动报错 java.lang.NullPointerException: nullat sun.awt.FontConfiguration.getVersion(FontConfi ...
- 转载:java程序员如何拿到2万月薪
作者:匿名用户链接:https://www.zhihu.com/question/39890405/answer/83676977来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- HDU 1264 Counting Squares(线段树求面积的并)
Counting Squares Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- Java利用递归算法统计1-6的数组排列组合数
Java利用递归算法统计1-6的数组排列组合数 1.设计源码 /** * @Title:ArrayCombination.java * @Package:com.you.data * @Descrip ...
- Java开发人员必须掌握的Linux命令-学以致用(5)
================================================= 人工智能教程.零基础!通俗易懂!风趣幽默!大家可以看看是否对自己有帮助! 点击查看高清无码教程 == ...
- IDEA报错: Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.datasource.url' in value "${spring.datasource.url}"
运行审核流模块: 在ActivitiServiceApplication模块日志报错: Error starting ApplicationContext. To display the auto-c ...
- java.sql.SQLSyntaxErrorException: ORA-01722: 无效数字
### Error updating database. Cause: java.sql.SQLSyntaxErrorException: ORA-01722: 无效数字 ### The error ...
- 20155321 2016-2017-2 《Java程序设计》第三周学习总结
20155321 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 4.1 类与对象 定义类用class关键字,建立实例用new关键字 一个原始码中可有多个类定 ...
随机推荐
- [信息收集]11种绕过CDN查找真实IP方法【转载】
今天在看一些有关CDN的文章的时候,发现一篇写的蛮好的文章,故转载过来. 原文链接:https://www.cnblogs.com/qiudabai/p/9763739.html 0x01 验证是否存 ...
- Spring学习随笔(1):为什么要使用Spring
寒冷的冬天,一周两节课,掏出买了一年没翻过的<Spring实战>. 刚刚接触spring的我对它还不是很熟悉,对各种知识的认知也比较浅薄,但我会学习的过程通过随笔记录下来,监督自己学下去. ...
- 2018-2019-2 20165114《网络对抗技术》Exp7 网络欺诈防范
Exp7 网络欺诈防范 目录 一.实验内容 二.基础问题回答 (1)通常在什么场景下容易受到DNS spoof攻击 (2)在日常生活工作中如何防范以上两攻击方法 三.实践过程记录 3.1简单应用SET ...
- CentOS7 修改设置静态IP和DNS
最近因为学习Puppet,用虚拟机装了个CentOS,使用的NAT的网络模式,为了防止再次启动系统的时候网络IP发生变化,因此设置静态IP和DNS. 由于CentOS是最小化安装,没有ifconfig ...
- vue开发环境、正式环境的配置及原理
修改prod.env.js里的内容,修改后的内容如下: 'use strict' module.exports = { NODE_ENV: '"production"', EVN_ ...
- HTML5 地理位置定位API(3)
HTML5 地理位置定位实例 这篇文章主要为大家介绍了HTML5地理定位的方法,实例讲述了html5获取坐标完整实现过程, 并对比不同浏览器运行效果给出参考结果,需要的朋友可以参考下 本文实例讲述了h ...
- 002-创建型-02-抽象工厂模式(Abstract Factory)
一.概述 抽象工厂模式提供同一个创建一系列相关或相互依赖对象的接口,无须指定它们具体的类 抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态.抽象工厂模式是指当有多个抽象角色时,使用的一 ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_15-细粒度授权-我的课程细粒度授权-实现
先定义接口 实现接口 service 需要通过conpanyId去查询课程的列表 定义dao 要查课程的图片 名称 等相关信息.所以使用Mybatis来实现 定义Mapper 看这个dao里面方法在哪 ...
- Java高并发程序设计
一.并行世界 摩尔定律的失效,2004年秋季,Intel宣布彻底取消4GHz计划,CPU向多核心的发展,顶级计算机科学家唐纳德丶尔文丶克努斯评价:在我看来,这种现象(并发)或多或少是由于硬件设计者已经 ...
- java精确计算工具类
java精确计算工具类 import java.math.BigDecimal; import java.math.RoundingMode; import java.math.BigDecimal; ...