poj2826 An Easy Problem?!(计算几何)
传送门
•题意
两根木块组成一个槽,给定两个木块的两个端点
雨水竖直下落,问槽里能装多少雨水,
•思路
找不能收集到雨水的情况
我们令线段较高的点为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-12; 10 const double inf = 1e20; 11 const double pi = acos(-1.0); 12 const int maxp = 1010; 13 //`Compares a double to zero` 14 int sgn(double x){ 15 if(fabs(x) < eps)return 0; 16 if(x < 0)return -1; 17 else return 1; 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) == 0 && sgn(y-b.y) == 0; 59 } 60 bool operator < (Point b)const{ 61 return sgn(x-b.x)== 0?sgn(y-b.y)<0: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/2) == 0){ 169 e = (s + Point(0,1)); 170 } 171 else{ 172 e = (s + Point(1,tan(angle))); 173 } 174 } 175 //ax+by+c=0 176 Line(double a,double b,double c){ 177 if(sgn(a) == 0){ 178 s = Point(0,-c/b); 179 e = Point(1,-c/b); 180 } 181 else if(sgn(b) == 0){ 182 s = Point(-c/a,0); 183 e = Point(-c/a,1); 184 } 185 else{ 186 s = Point(0,-c/b); 187 e = Point(1,(-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) < 0)k += pi; 210 if(sgn(k-pi) == 0)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 < 0)return 1; 220 else if(c > 0)return 2; 221 else return 3; 222 } 223 // 点在线段上的判断 224 bool Pointonseg(Point p){ 225 return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <= 0; 226 } 227 //`两向量平行(对应直线平行或重合)` 228 bool parallel(Line v){ 229 return sgn((e-s)^(v.e-v.s)) == 0; 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)==-2 && (d3^d4)==-2 )return 2; 241 return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) || 242 (d2==0 && sgn((v.e-s)*(v.e-e))<=0) || 243 (d3==0 && sgn((s-v.s)*(s-v.e))<=0) || 244 (d4==0 && sgn((e-v.s)*(e-v.e))<=0); 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)==-2) return 2; 255 return (d1==0||d2==0); 256 } 257 //`两直线关系` 258 //`0 平行` 259 //`1 重合` 260 //`2 相交` 261 int linecrossline(Line v){ 262 if((*this).parallel(v)) 263 return v.relation(s)==3; 264 return 2; 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))<0 || sgn((p-e)*(s-e))<0) 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(2*q.x-p.x,2*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=-1; 325 if(l1.parallel(l2))///平行或重合 326 s=0; 327 else if((!l1.angle())||(!l2.angle()))///k=0 328 s=0; 329 else if(l1.segcrossseg(l2)==0)///不相交 330 s=0; 331 else if(l1.segcrossseg(l2))///相交 332 { 333 Point P=l1.intersection(l2);///获得交点 334 Point p1,p2; 335 int flag=0,flag1=0; 336 if(l1.s.y-P.y>eps) p1=l1.s,flag=1; 337 if(l2.s.y-P.y>eps) p2=l2.s,flag1=1; 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>0?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>0?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=0; 372 } 373 printf("%.2f\n",s); 374 } 375 }View Code
转载于:https://www.cnblogs.com/MMMinoz/p/11492764.html
poj2826 An Easy Problem?!(计算几何)相关推荐
- POJ - 2826 An Easy Problem?!(计算几何,好题)
题目链接:点击查看 题目大意:给出两条线段,问组成的容器最多能接多少雨水 题目分析:既然是接雨水,那么肯定只能是漏斗状,很容易排除掉两种情况: 其中有一条线段平行于x轴 两条线段不相交 还有一种比较难 ...
- POJ 2826 An Easy Problem?! 叉积求多边形面积 【计算几何】
ACM博客_kuangbin POJ 2826 An Easy Problem?! An Easy Problem?! Time Limit: 1000MS Memory Limit: 65536 ...
- 数论六之计算几何——An Easy Problem,Ancient Berland Circus,Open-air shopping malls
可检验模板正确度 An Easy Problem?! Ancient Berland Circus Open-air shopping malls An Easy Problem?! problem ...
- 2019年ICPC银川区域赛 Easy Problem(简单莫比乌斯函数 + 欧拉降幂)
Easy Problem ∑a1=1m∑a2=1m∑a3=1m⋯∑an−1m∑anm[gcd(a1,a2,a3,-,an−1,an)==d](a1,a2,a3,-,an−1,an)k=dkd∑a1=1 ...
- 信息学奥赛一本通 1223:An Easy Problem | OpenJudge NOI 4.6 1455:An Easy Problem
[题目链接] ybt 1223:An Easy Problem OpenJudge NOI 4.6 1455:An Easy Problem [题目考点] 1. 数制 2. 枚举 [解题思路] 解法1 ...
- 信息学奥赛一本通(1223:An Easy Problem)
1223:An Easy Problem 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 5835 通过数: 4111 [题目描述] 给定一个正整数N,求最 ...
- 【UVA】11991 Easy Problem from Rujia Liu? (整数v第k次出现在什么位置)
https://vjudge.net/problem/UVA-11991 题目大意:就是给你一个序列,然后给出k和v,看整数v第k次出现在该序列的什么位置,没有的话就输出0 结构体(略复杂): #in ...
- 数学--数论-- HDU 2601 An easy problem(约束和)
Problem Description When Teddy was a child , he was always thinking about some simple math problems ...
- CodeForces - 1058A. In Search of an Easy Problem
这题,全零是esay有1是hard,真难呀. #include<bits/stdc++.h> using namespace std; int main(){int n,i,x,flag= ...
最新文章
- leetcode python 032 识别最长合法括号
- Linux下三大最佳的开源视频播放器
- luoguP1419 寻找段落(二分答案+单调队列)
- boost::geometry::strategy::simplify::douglas_peucker用法的测试程序
- C# 报警 控制蜂鸣器发声
- linux 下创建GRE隧道
- 数据库工作笔记008---pg_hba.conf entry for host “192.168.2.111”, user “gpadmin”, database “template1”, SSL
- python小括号( )与中括号 [ ]
- python unittest教程_python unittest 基本介绍
- 基于粒子群优化算法的BP神经网络预测模型(Matlab代码实现)
- 三调专题(一)宗地四至提取的量化算法及FME实现
- 最新稳定短视频去水印免费解析API接口分享
- java输出罗马数字_java工具类——罗马数字和阿拉伯数字相互转换
- docker run参数-v的rw、ro详解
- android 4.4.2 安全漏洞修复
- 数据科学入门前需要知道的10件事
- Thunderbird 邮件签名三个实现方式
- fluent-mybatis初体验
- 算法设计与分析: 5-22 魔方(Rubik's Cube)问题
- python中文编辑_python用Tkinter做自己的中文代码编辑器
热门文章
- MySQL修改数据类型语句
- 世界公认最好的记忆方法_全球公认最好的12个教育孩子的方法,值得每个家长收藏学习!...
- python故事书_python的故事
- Apache common包应用集合
- Oracle数据库修改字段类型
- chrome浏览器无法上网_低调使用,内置特殊功能的浏览器。。
- android设置输入框输入字符限制,Android里限制EditText控件可以输入字符内容的范围的方法...
- 使用未初始化的内存是什么意思_单根内存条的极限容量是多少?内存条上的2R X 8代表了什么意思?...
- 两次深度debug经历,希望大家不要踩坑
- 在 Windows上写 Python 代码的最佳组合!