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 ...
随机推荐
- C++ VS2013环境编译使用sqlite数据库全过程
转载:http://www.cnblogs.com/imoon/archive/2012/11/30/2796726.html 转载:https://blog.csdn.net/hjm4702192/ ...
- idata,xdata,pdata,code
data ---> 可寻址片内ram bdata ---> 可位寻址的片内ram idata ---> 可寻址片内ram,允许访问全部内部ra ...
- Python3基础 str endswith 是否以指定字符串结束
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- 51nod 1413 权势二进制
本来刚开始还是想用每一位 -1的个数 然后再乘以10 不断累加 后来发现 完全不是这回事啊 因为本身就是0 和 1 所以只要记录出现的最大的数字 就是答案 因为 n >= 1 // 所以不 ...
- 从nodejs到在线商城
nodejs安装express开发框架 (开发环境:mkdir nodeshop && cd nodeshop > npm init > npm install expre ...
- Java8的新特性,二进制序列转十进制数字
package kata_007_二进制序列转十进制int; /** * java8 Lambda表达式转换binary序列->十进制数 */ import java.util.ArrayLis ...
- C#学习笔记(十):函数和参数
函数 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syste ...
- cent os下搭建简单的服务器
作为常和网络打交道的程序员,经常会遇到需要服务器的场合,比如搭建一个web服务器,一个代理服务器,又或者一个小型的游戏服务器. 我时常和朋友一起玩一款叫我的世界的游戏,为了能够长期稳定地联机玩,所以特 ...
- 下列java代码中的变量a、b、c分别在内存的______存储区存放。
class A{ private String a = "aa"; public boolean methodB(){ String b = "sb"; fin ...
- poj 2480 Longge's problem 欧拉函数+素数打表
Longge's problem Description Longge is good at mathematics and he likes to think about hard mathem ...