sgu 129 Inheritance 凸包,线段交点,计算几何 难度:2
129. Inheritance
time limit per test: 0.25 sec.
memory limit per test: 4096 KB
The old King decided to divide the Kingdom into parts among his three sons. Each part is a polygonal area. Taking into account the bad temper of the middle son the King gave him a part of Kingdom such that moving straight from any place of this part to any other place of this part he will not cross the boundary.
There are several mineral deposits in the Kingdom. Each mineral deposit looks like a straight line segment. The middle son wants to know what part of mineral deposits is located inside his territory (not including the boundaries).
Input
The first line contains an integer N (3<=N<=400) - the number of vertexes of the polygon boundaring the territory of King's middle son. Each i-th line of the next N lines contains pair of integers xi, yi (0<=xi,yi<=30000) - a position of the i-th vertex (3<=i<=400). The vertexes are given in random order. There are no any three vertexes laying on a straight line. The next line includes the only integer M (2<=M<=1000) - the number of mineral deposits in the Kingdom. Each j-th line of the next M lines contains two pairs of integers aj1, bj1 - point of the beginning and aj2, bj2 - point of the end of the j-th mineral deposit (0<=aj1,bj1,aj2,bj2<=30000, for 1<=j<=M). The numbers in each line are divided by spaces.
Output
Output file should contain M lines. Each j-th line should contain a real number Lj calculated with precision 0.01 - the lehgth of the middle son's part of j-th mineral deposit.
Sample Input
3
1 1
6 1
1 6
4
1 2 1 4
2 2 2 4
4 2 4 4
6 2 6 4
Sample Output
0
2
1
0 思路很简单,就是涉及到了多个计算几何的知识点
1 领地点都是凸包上的点,需要按照凸包排个序,确定了左下点之后按逆时针排个序就行
2 对于线段,完全列举一下凸包的所有边,看有多少交点即可(一定只有<=2个)
3 对于和凸包有交点的线段,如果两个相邻点的中点在凸包内,那么这俩因为本来就是边界了,所以一定这一段在凸包里,如果没有交点,要是线段中点在凸包内也一样
4 如何判断线段交点?...设线段A=P+t1*v(v是方向向量,P是起点),B=Q+t2*w(w向量,Q起点),u=P-Q,则t1=cross(w,u)/cross(v,w),t2=cross(v,u)/cross(v,w),线段交点要满足t1,t2属于[0,1],满足条件后带入即可
5 如何确定点是否在凸包内?设凸包点集为P,(P按凸包已经排好了,)对于所有的线段p[(i+1)%n],p[i] ,因为P构成了凸包,所以只需要都在左侧即可.(转角法缩略版),画个图看看就懂
注意:使用复数的叉积不知道为什么不行?也许是我的姿势不对
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const double eps=1e-8;
int dcmp(double d){
if(fabs(d)<eps)return 0;
return d>0?1:-1;
}
struct pnt{
double x,y;
pnt():x(0),y(0){}
pnt(double tx,double ty):x(tx),y(ty){}
pnt operator -(pnt p2){
pnt newp(x-p2.x,y-p2.y);
return newp;
}
pnt operator +(pnt p2){
pnt newp(x+p2.x,y+p2.y);
return newp;
}
pnt operator *(double d){
pnt newp(x*d,y*d);
return newp;
}
pnt operator /(double d){
pnt newp(x/d,y/d);
return newp;
}
double dis(pnt p2){
return sqrt((x-p2.x)*(x-p2.x)+(y-p2.y)*(y-p2.y));
}
bool operator ==(pnt p2){
if(dcmp(x-p2.x)==0&&dcmp(y-p2.y)==0)return true;
return false;
}
};
pnt p[2000],inset[2000][2],seg[2000][2];
int n,m,len[2000];
double cross(pnt p1,pnt p2){
return p1.x*p2.y-p1.y*p2.x;
}
bool cmpx(pnt p1,pnt p2){
if(p1.x!=p2.x)return p1.x<p2.x;
return p1.y<p2.y;
}
bool cmp(pnt p1,pnt p2){
return cross(p1-p[0],p2-p[0])<0;
} int isPointInConvexPolygon(pnt p1){
for(int i=0;i<n;i++){
pnt A=pnt(p[(i+1)%n].x-p[i].x,p[(i+1)%n].y-p[i].y);
pnt B=pnt(p1.x-p[i].x,p1.y-p[i].y);
int fl=dcmp(cross(A,B));
if(fl>0)return 0;
if(fl==0){
int maxx=max(p[(i+1)%n].x,p[i].x);
int minx=min(p[(i+1)%n].x,p[i].x);
int maxy=max(p[(i+1)%n].y,p[i].y);
int miny=min(p[(i+1)%n].y,p[i].y);
if(minx<=p1.x&&maxx>=p1.x&&miny<=p1.y&&maxy>=p1.y)return -1;
}
}
return 1;
}
void getinsertpoint(){
for(int i=0;i<n;i++){
pnt v=p[(i+1)%n]-p[i];
for(int j=0;j<m;j++){
pnt w=seg[j][1]-seg[j][0];
if(dcmp(cross(v,w))==0)continue;
pnt u=p[i]-seg[j][0];
double t=cross(w,u)/cross(v,w);
double t2=cross(v,u)/cross(v,w);
if(t2+eps>1||t2+eps<0)continue;
if(t<1+eps&&t+eps>0){
pnt newp=p[i]+v*t;
bool fl=true;
for(int k=0;k<len[j];k++){
if(newp==inset[j][k])fl=false;
}
if(fl)inset[j][len[j]++]=newp;
}
}
}
}
void getlength(){
for(int i=0;i<m;i++){
double leng=0;
if(len[i]==2){
pnt mid1=(seg[i][0]+inset[i][0])/2;
int stamid=isPointInConvexPolygon(mid1);
if(stamid==1){
leng+=seg[i][0].dis(inset[i][0]);
}
mid1=(inset[i][0]+inset[i][1])/2;
stamid=isPointInConvexPolygon(mid1);
if(stamid==1){
leng+=inset[i][0].dis(inset[i][1]);
}
mid1=(seg[i][1]+inset[i][1])/2;
stamid=isPointInConvexPolygon(mid1);
if(stamid==1){
leng+=seg[i][1].dis(inset[i][1]);
}
}
else if(len[i]==1){
pnt mid1=(seg[i][0]+inset[i][0])/2;
int stamid=isPointInConvexPolygon(mid1);
if(stamid==1){
leng+=seg[i][0].dis(inset[i][0]);
}
mid1=(seg[i][1]+inset[i][0])/2;
stamid=isPointInConvexPolygon(mid1);
if(stamid==1){
leng+=seg[i][1].dis(inset[i][0]);
}
}
else if(len[i]==0){
pnt mid1=(seg[i][1]+seg[i][0])/2;
int stamid=isPointInConvexPolygon(mid1);
if(stamid==1){
leng+=seg[i][1].dis(seg[i][0]);
}
}
printf("%.2f\n",leng);
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
scanf("%d",&m);
for(int i=0;i<m;i++){
scanf("%lf%lf%lf%lf",&seg[i][0].x,&seg[i][0].y,&seg[i][1].x,&seg[i][1].y);
}
for(int i=0;i<m;i++){
sort(seg[i],seg[i]+2,cmpx);
}
sort(p,p+n,cmpx);
sort(p+1,p+n,cmp);
getinsertpoint();
for(int i=0;i<m;i++){
sort(inset[i],inset[i]+len[i],cmpx);
}
getlength();
return 0;
}
sgu 129 Inheritance 凸包,线段交点,计算几何 难度:2的更多相关文章
- hdu 2857:Mirror and Light(计算几何,点关于直线的对称点,求两线段交点坐标)
Mirror and Light Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 谈谈"求线段交点"的几种算法(js实现,完整版)
"求线段交点"是一种非常基础的几何计算, 在很多游戏中都会被使用到. 下面我就现学现卖的把最近才学会的一些"求线段交点"的算法总结一下, 希望对大家有所帮助. ...
- EDU 50 E. Covered Points 利用克莱姆法则计算线段交点
E. Covered Points 利用克莱姆法则计算线段交点.n^2枚举,最后把个数开方,从ans中减去. ans加上每个线段的定点数, 定点数用gcs(△x , △y)+1计算. #include ...
- Inheritance - SGU 129(线段与多边形相交的长度)
题目大意:给一个凸多边形(点不是按顺序给的),然后计算给出的线段在这个凸多边形里面的长度,如果在边界不计算. 分析:WA2..WA3...WA4..WA11...WA的无话可说,总之细节一定考虑清楚, ...
- hdu 1086(计算几何入门题——计算线段交点个数)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1086 You can Solve a Geometry Problem too Time Limit: 2 ...
- 【计算几何初步-线段相交】【HDU1089】线段交点
You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/3 ...
- Codeforces Gym100543B 计算几何 凸包 线段树 二分/三分 卡常
原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100543B.html 题目传送门 - CF-Gym100543B 题意 给定一个折线图,对于每一条 ...
- SGU 110. Dungeon 计算几何 难度:3
110. Dungeon time limit per test: 0.25 sec. memory limit per test: 4096 KB The mission of space expl ...
- poj 3348 Cows 凸包 求多边形面积 计算几何 难度:0 Source:CCC207
Cows Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7038 Accepted: 3242 Description ...
随机推荐
- ZedGraph如何动态的加载曲线
ZedGraph的在线文档 http://zedgraph.sourceforge.net/documentation/default.html 官网的源代码 http://sourceforge.n ...
- 【第三十一章】 elk(2)- 第二种架构(最常用架构)
参考:http://linuxg.blog.51cto.com/4410110/1761757 最常用架构: 一.安装redis 1.下载:http://redis.io/download 2.解压后 ...
- Java 多线程 破解密码 demo
功能要求: 具体类: Decrypt 测试类,用来启动破解和日志线程 DecryptThread 破解线程类,用来生成测试的字符串,并暴力破解 LogThread 日志类,将输出每次生成的字符串结果 ...
- C# SQLite数据库操作
WinCE项目开发 VS2008 自己写的SQLite数据库管理类代码如下: SQLiteManager.cs using System.Data; using System.Data.SQLit ...
- 【Coursera】Fifth week(3)
Ethernet 在 PARC(Xerox) 发明. 第一个 Local-Area-Network (LAN 局域网). 把 PCs 连接到 激光打印机上. 在夏威夷大学,被早期的无线网络 Aloha ...
- MySQL会创建临时表的几种情况
1.UNION查询: 2.用到TEMPTABLE算法或者是UNION查询中的视图: 3.ORDER BY和GROUP BY的子句不一样时: 4.表连接中,ORDER BY的列不是驱动表中的:(指定了联 ...
- java ShutdownHook介绍与使用
Java程序经常也会遇到进程挂掉的情况,一些状态没有正确的保存下来,这时候就需要在JVM关掉的时候执行一些清理现场的代码.JAVA中的ShutdownHook提供了比较好的方案. JDK提供了Java ...
- shell 清空指定大小的日志文件
#!/bin/bash # 当/var/log/syslog大于68B时 if ! [ -f /var/log/syslog ] then echo "file not exist!&quo ...
- 代码中特殊的注释技术 -- TODO、FIXME和XXX的用处
借鉴地址:https://www.cnblogs.com/pengyingh/articles/2445826.html 在阅读一些代码时,经常会遇到诸如:TODO.FIXME和XXX的单词,它们是有 ...
- 模型层model layer
题外话: Django的教程写到这里,就进入了整体的第二部分,也是最关键的部分.此时有一个问题必须想清楚,那就是,以项目带动内容还是以参考书目的方式展开?为此,我考虑了很久. 我在开始学习Django ...