传送门

•题意

两根木块组成一个槽,给定两个木块的两个端点

雨水竖直下落,问槽里能装多少雨水,

•思路

找不能收集到雨水的情况

我们令线段较高的点为s点,较低的点为e点

①两条木块没有交点

②平行或重合

③至少有一条木块水平(雨水会滑落)

④形成覆盖,如"$\wedge $","人",还有比较难想的上边长下边短的情况

  • 其中形成"$\wedge$"型和"人"型 都是两条线段的交点比两条线段中较低的s点同高,

      也就是不大于较高的s点

  • 上长下短的覆盖是两个s点都大于交点而不能存水的唯一情况

     如上图,我们可以在a.x出从b上引一条竖直线,看是否与a有交点,如果有说明覆盖了

能收集到雨水的情况要注意 水面与较低的s点水平

•代码

  1. //#include<bits/stdc++.h>
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7.  
  8. // `计算几何模板`
  9. const double eps = 1e-;
  10. const double inf = 1e20;
  11. const double pi = acos(-1.0);
  12. const int maxp = ;
  13. //`Compares a double to zero`
  14. int sgn(double x){
  15. if(fabs(x) < eps)return ;
  16. if(x < )return -;
  17. else return ;
  18. }
  19. //square of a double
  20. inline double sqr(double x){return x*x;}
  21. /*
  22. * Point
  23. * Point() - Empty constructor
  24. * Point(double _x,double _y) - constructor
  25. * input() - double input
  26. * output() - %.2f output
  27. * operator == - compares x and y
  28. * operator < - compares first by x, then by y
  29. * operator - - return new Point after subtracting curresponging x and y
  30. * operator ^ - cross product of 2d Points
  31. * operator * - dot product
  32. * len() - gives length from origin
  33. * len2() - gives square of length from origin
  34. * distance(Point p) - gives distance from p
  35. * operator + Point b - returns new Point after adding curresponging x and y
  36. * operator * double k - returns new Point after multiplieing x and y by k
  37. * operator / double k - returns new Point after divideing x and y by k
  38. * rad(Point a,Point b)- returns the angle of Point a and Point b from this Point
  39. * trunc(double r) - return Point that if truncated the distance from center to r
  40. * rotleft() - returns 90 degree ccw rotated Point
  41. * rotright() - returns 90 degree cw rotated Point
  42. * rotate(Point p,double angle) - returns Point after rotateing the Point centering at p by angle radian ccw
  43. */
  44. struct Point{
  45. double x,y;
  46. Point(){}
  47. Point(double _x,double _y){
  48. x = _x;
  49. y = _y;
  50. }
  51. void input(){
  52. scanf("%lf%lf",&x,&y);
  53. }
  54. void output(){
  55. printf("%.2f %.2f\n",x,y);
  56. }
  57. bool operator == (Point b)const{
  58. return sgn(x-b.x) == && sgn(y-b.y) == ;
  59. }
  60. bool operator < (Point b)const{
  61. return sgn(x-b.x)== ?sgn(y-b.y)<:x<b.x;
  62. }
  63. Point operator -(const Point &b)const{
  64. return Point(x-b.x,y-b.y);
  65. }
  66. //叉积
  67. double operator ^(const Point &b)const{
  68. return x*b.y - y*b.x;
  69. }
  70. //点积
  71. double operator *(const Point &b)const{
  72. return x*b.x + y*b.y;
  73. }
  74. //返回长度
  75. double len(){
  76. return hypot(x,y);//库函数
  77. }
  78. //返回长度的平方
  79. double len2(){
  80. return x*x + y*y;
  81. }
  82. //返回两点的距离
  83. double distance(Point p){
  84. return hypot(x-p.x,y-p.y);
  85. }
  86. Point operator +(const Point &b)const{
  87. return Point(x+b.x,y+b.y);
  88. }
  89. Point operator *(const double &k)const{
  90. return Point(x*k,y*k);
  91. }
  92. Point operator /(const double &k)const{
  93. return Point(x/k,y/k);
  94. }
  95. //`计算pa 和 pb 的夹角`
  96. //`就是求这个点看a,b 所成的夹角`
  97. //`测试 LightOJ1203`
  98. double rad(Point a,Point b){
  99. Point p = *this;
  100. return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));
  101. }
  102. //`化为长度为r的向量`
  103. Point trunc(double r){
  104. double l = len();
  105. if(!sgn(l))return *this;
  106. r /= l;
  107. return Point(x*r,y*r);
  108. }
  109. //`逆时针旋转90度`
  110. Point rotleft(){
  111. return Point(-y,x);
  112. }
  113. //`顺时针旋转90度`
  114. Point rotright(){
  115. return Point(y,-x);
  116. }
  117. //`绕着p点逆时针旋转angle`
  118. Point Rotate(Point p,double angle){
  119. Point v = (*this) - p;
  120. double c = cos(angle), s = sin(angle);
  121. return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c);
  122. }
  123. };
  124. /*
  125. * Stores two Points
  126. * Line() - Empty constructor
  127. * Line(Point _s,Point _e) - Line through _s and _e
  128. * operator == - checks if two Points are same
  129. * Line(Point p,double angle) - one end p , another end at angle degree
  130. * Line(double a,double b,double c) - Line of equation ax + by + c = 0
  131. * input() - inputs s and e
  132. * adjust() - orders in such a way that s < e
  133. * length() - distance of se
  134. * angle() - return 0 <= angle < pi
  135. * relation(Point p) - 3 if Point is on line
  136. * 1 if Point on the left of line
  137. * 2 if Point on the right of line
  138. * Pointonseg(double p) - return true if Point on segment
  139. * parallel(Line v) - return true if they are parallel
  140. * segcrossseg(Line v) - returns 0 if does not intersect
  141. * returns 1 if non-standard intersection
  142. * returns 2 if intersects
  143. * linecrossseg(Line v) - line and seg
  144. * linecrossline(Line v) - 0 if parallel
  145. * 1 if coincides
  146. * 2 if intersects
  147. * crossPoint(Line v) - returns intersection Point
  148. * disPointtoline(Point p) - distance from Point p to the line
  149. * disPointtoseg(Point p) - distance from p to the segment
  150. * dissegtoseg(Line v) - distance of two segment
  151. * lineprog(Point p) - returns projected Point p on se line
  152. * symmetryPoint(Point p) - returns reflection Point of p over se
  153. *
  154. */
  155. struct Line{
  156. Point s,e;
  157. Line(){}
  158. Line(Point _s,Point _e){
  159. s = _s;
  160. e = _e;
  161. }
  162. bool operator ==(Line v){
  163. return (s == v.s)&&(e == v.e);
  164. }
  165. //`根据一个点和倾斜角angle确定直线,0<=angle<pi`
  166. Line(Point p,double angle){
  167. s = p;
  168. if(sgn(angle-pi/) == ){
  169. e = (s + Point(,));
  170. }
  171. else{
  172. e = (s + Point(,tan(angle)));
  173. }
  174. }
  175. //ax+by+c=0
  176. Line(double a,double b,double c){
  177. if(sgn(a) == ){
  178. s = Point(,-c/b);
  179. e = Point(,-c/b);
  180. }
  181. else if(sgn(b) == ){
  182. s = Point(-c/a,);
  183. e = Point(-c/a,);
  184. }
  185. else{
  186. s = Point(,-c/b);
  187. e = Point(,(-c-a)/b);
  188. }
  189. }
  190. void input(){
  191. s.input();
  192. e.input();
  193. }
  194. //根据x排序
  195. void adjustx(){
  196. if(e < s)swap(s,e);
  197. }
  198. //根据y排序
  199. void adjusty(){
  200. if(e.y>s.y) swap(s,e);
  201. }
  202. //求线段长度
  203. double length(){
  204. return s.distance(e);
  205. }
  206. //`返回直线倾斜角 0<=angle<pi`
  207. double angle(){
  208. double k = atan2(e.y-s.y,e.x-s.x);
  209. if(sgn(k) < )k += pi;
  210. if(sgn(k-pi) == )k -= pi;
  211. return k;
  212. }
  213. //`点和直线关系`
  214. //`1 在左侧`
  215. //`2 在右侧`
  216. //`3 在直线上`
  217. int relation(Point p){
  218. int c = sgn((p-s)^(e-s));
  219. if(c < )return ;
  220. else if(c > )return ;
  221. else return ;
  222. }
  223. // 点在线段上的判断
  224. bool Pointonseg(Point p){
  225. return sgn((p-s)^(e-s)) == && sgn((p-s)*(p-e)) <= ;
  226. }
  227. //`两向量平行(对应直线平行或重合)`
  228. bool parallel(Line v){
  229. return sgn((e-s)^(v.e-v.s)) == ;
  230. }
  231. //`两线段相交判断`
  232. //`2 规范相交`
  233. //`1 非规范相交`
  234. //`0 不相交`
  235. int segcrossseg(Line v){
  236. int d1 = sgn((e-s)^(v.s-s));
  237. int d2 = sgn((e-s)^(v.e-s));
  238. int d3 = sgn((v.e-v.s)^(s-v.s));
  239. int d4 = sgn((v.e-v.s)^(e-v.s));
  240. if( (d1^d2)==- && (d3^d4)==- )return ;
  241. return (d1== && sgn((v.s-s)*(v.s-e))<=) ||
  242. (d2== && sgn((v.e-s)*(v.e-e))<=) ||
  243. (d3== && sgn((s-v.s)*(s-v.e))<=) ||
  244. (d4== && sgn((e-v.s)*(e-v.e))<=);
  245. }
  246. //`直线和线段相交判断`
  247. //`-*this line -v seg`
  248. //`2 规范相交`
  249. //`1 非规范相交`
  250. //`0 不相交`
  251. int linecrossseg(Line v){
  252. int d1 = sgn((e-s)^(v.s-s));
  253. int d2 = sgn((e-s)^(v.e-s));
  254. if((d1^d2)==-) return ;
  255. return (d1==||d2==);
  256. }
  257. //`两直线关系`
  258. //`0 平行`
  259. //`1 重合`
  260. //`2 相交`
  261. int linecrossline(Line v){
  262. if((*this).parallel(v))
  263. return v.relation(s)==;
  264. return ;
  265. }
  266. //`求两直线的交点`
  267. //`要保证两直线不平行或重合`
  268. Point crossPoint(Line v){
  269. double a1 = (v.e-v.s)^(s-v.s);
  270. double a2 = (v.e-v.s)^(e-v.s);
  271. return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
  272. }
  273. //点到直线的距离
  274. double disPointtoline(Point p){
  275. return fabs((p-s)^(e-s))/length();
  276. }
  277. //点到线段的距离
  278. double disPointtoseg(Point p){
  279. if(sgn((p-s)*(e-s))< || sgn((p-e)*(s-e))<)
  280. return min(p.distance(s),p.distance(e));
  281. return disPointtoline(p);
  282. }
  283. //`返回线段到线段的距离`
  284. //`前提是两线段不相交,相交距离就是0了`
  285. double dissegtoseg(Line v){
  286. return min(min(disPointtoseg(v.s),disPointtoseg(v.e)),min(v.disPointtoseg(s),v.disPointtoseg(e)));
  287. }
  288. //`返回点p在直线上的投影`
  289. Point lineprog(Point p){
  290. return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );
  291. }
  292. //`返回点p关于直线的对称点`
  293. Point symmetryPoint(Point p){
  294. Point q = lineprog(p);
  295. return Point(*q.x-p.x,*q.y-p.y);
  296. }
  297. //求线段交点
  298. Point intersection(Line v)
  299. {
  300. double a1,a2,b1,b2,c1,c2;
  301. a1=s.y-e.y;
  302. a2=v.s.y-v.e.y;
  303. b1=e.x-s.x;
  304. b2=v.e.x-v.s.x;
  305. c1=s.x*e.y-e.x*s.y;
  306. c2=v.s.x*v.e.y-v.e.x*v.s.y;
  307. return Point((c1*b2-c2*b1)/(a2*b1-a1*b2),(c1*a2-c2*a1)/(b2*a1-b1*a2));
  308. }
  309. };
  310. int main()
  311. {
  312. int t;
  313. scanf("%d",&t);
  314. while(t--)
  315. {
  316. double a,b,c,d;
  317. Line l1,l2,l3,l4;
  318. scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
  319. l1=Line(Point(a,b),Point(c,d));
  320. scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
  321. l2=Line(Point(a,b),Point(c,d));
  322. l1.adjusty(),l2.adjusty();
  323.  
  324. double s=-;
  325. if(l1.parallel(l2))///平行或重合
  326. s=;
  327. else if((!l1.angle())||(!l2.angle()))///k=0
  328. s=;
  329. else if(l1.segcrossseg(l2)==)///不相交
  330. s=;
  331. else if(l1.segcrossseg(l2))///相交
  332. {
  333. Point P=l1.intersection(l2);///获得交点
  334. Point p1,p2;
  335. int flag=,flag1=;
  336. if(l1.s.y-P.y>eps) p1=l1.s,flag=;
  337. if(l2.s.y-P.y>eps) p2=l2.s,flag1=;
  338. if(flag&&flag1)
  339. {///还有一种情况没有水。上面的y把下面的y覆盖---遮挡判断
  340. if(p1.y-p2.y>eps)
  341. {
  342. if(l1.segcrossseg(Line(p2,Point(p2.x,p1.y+2.0))))
  343. {
  344. printf("0.00\n");
  345. continue;
  346. }
  347. }
  348. if(p2.y-p1.y>eps)
  349. {
  350. if(l2.segcrossseg(Line(p1,Point(p1.x,p2.y+2.0))))
  351. {
  352. printf("0.00\n");
  353. continue;
  354. }
  355. }
  356. if(p1.y-p2.y>eps)
  357. {
  358. ///取p1.x的水平和p2.y,p1与p2.x的交点
  359. ///水面和低处水平
  360. double x=p1.x>?p1.x+1.00:p1.x-1.0;
  361. p1=l1.intersection(Line(Point(x,p2.y),Point(-x,p2.y)));
  362. }
  363. else
  364. {
  365. double x=p2.x>?p2.x+1.00:p2.x-1.0;
  366. p2=l2.intersection(Line(Point(x,p1.y),Point(-x,p1.y)));
  367. }
  368. s=fabs((p1.x-p2.x)*(p1.y-P.y)*0.5)+eps;
  369. }
  370. else
  371. s=;
  372. }
  373. printf("%.2f\n",s);
  374. }
  375. }

poj2826 An Easy Problem?!(计算几何)的更多相关文章

  1. poj2826 An Easy Problem?!【计算几何】

    含[三点坐标计算面积].[判断两线段是否有交点].[求线段交点]模板   An Easy Problem?! Time Limit: 1000MS   Memory Limit: 65536K Tot ...

  2. POJ 2826 An Easy Problem?! --计算几何,叉积

    题意: 在墙上钉两块木板,问能装多少水.即两条线段所夹的中间开口向上的面积(到短板的水平线截止) 解法: 如图: 先看是否相交,不相交肯定不行,然后就要求出P与A,B / C,D中谁形成的向量是指向上 ...

  3. bnuoj 1053 EASY Problem (计算几何)

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=1053 [题意]:基本上就是求直线与圆的交点坐标 [题解]:这种题我都比较喜欢用二分,三分做,果然可以 ...

  4. Poj2826 An Easy Problem

    呵呵哒.WA了无数次,一开始想的办法最终发现都有缺陷.首先需要知道: 1)线段不相交,一定面积为0 2)有一条线段与X轴平行,面积一定为0 3)线段相交,但是能接水的三角形上面线段把下面的线段完全覆盖 ...

  5. HDU 5572 An Easy Physics Problem (计算几何+对称点模板)

    HDU 5572 An Easy Physics Problem (计算几何) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5572 Descripti ...

  6. An Easy Problem?!(细节题,要把所有情况考虑到)

    http://poj.org/problem?id=2826 An Easy Problem?! Time Limit: 1000MS   Memory Limit: 65536K Total Sub ...

  7. UVA-11991 Easy Problem from Rujia Liu?

    Problem E Easy Problem from Rujia Liu? Though Rujia Liu usually sets hard problems for contests (for ...

  8. An easy problem

    An easy problem Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Sub ...

  9. UVa 11991:Easy Problem from Rujia Liu?(STL练习,map+vector)

    Easy Problem from Rujia Liu? Though Rujia Liu usually sets hard problems for contests (for example, ...

随机推荐

  1. [React Native]升级React Native版本

    React Native正式版本还没发布,但是小版本基本上每个月都更新1-2次.9月11号又更新了0.33版本,其中有两个增强功能正好是项目中用到的. 添加Android6.0权限验证API Add ...

  2. GitHub Top 100 Objective-C 项目简介

    主要对当前 GitHub 排名前 100 的项目做一个简单的简介, 方便初学者快速了解到当前 Objective-C 在 GitHub 的情况. 若有任何疑问可通过微博@李锦发联系我 GitHub 地 ...

  3. php表单的种类

    1.text 2.color 3.date 4.datetime 5.email 6.month 7.number 8.range 9.search 10.tel 11.url 12.week 13. ...

  4. 2019-7-4-win10-uwp-处理用户点击关闭按钮

    title author date CreateTime categories win10 uwp 处理用户点击关闭按钮 lindexi 2019-07-04 09:28:57 +0800 2019- ...

  5. MUI - 引导页制作

    引导页制作 本文的引导页和[官方的引导页示例](https://github.com/dcloudio/mui/blob/master/examples/hello-mui/examples/guid ...

  6. mysql字段中提取汉字,去除数字以及字母

    如果只是删除尾部的中文,保留数据,可以用以下的简单方式 MySQL as num; +------+ | num | +------+ | +------+ DELIMITER $$ DROP FUN ...

  7. Spring Security 的登录密码验证过程 UsernamePasswordAuthenticationFilter

    认证过程如下 一.先判断请求(请求必须是post请求)地址是否为配置的 login-processing-url 值(默认/j_spring_security_check),如果不是,则放行,进入下一 ...

  8. Kubernetes弹性伸缩全场景解读(五) - 定时伸缩组件发布与开源

    前言 容器技术的发展让软件交付和运维变得更加标准化.轻量化.自动化.这使得动态调整负载的容量变成一件非常简单的事情.在kubernetes中,通常只需要修改对应的replicas数目即可完成.当负载的 ...

  9. 2019-8-31-dotnet-使用-MessagePack-序列化对象

    title author date CreateTime categories dotnet 使用 MessagePack 序列化对象 lindexi 2019-08-31 16:55:58 +080 ...

  10. 模板—点分治B(合并子树)(洛谷P4149 [IOI2011]Race)

    洛谷P4149 [IOI2011]Race 点分治作用(目前只知道这个): 求一棵树上满足条件的节点二元组(u,v)个数,比较典型的是求dis(u,v)(dis表示距离)满足条件的(u,v)个数. 算 ...