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 ...
随机推荐
- SmartOS之以太网精简协议栈TinyIP
做物联网,没有以太网怎么能行!基于Enc28j60,我们团队独立实现了以太网精简协议栈TinyIP,目前支持ARP/ICMP/TCP/UDP/DHCP,还缺一个DNS就完整了.TinyIP内置一个数据 ...
- trigger自动执行事件
html <button>点击文字变红</button> <p>trigger出发点击事件</p> js $('button').click(funct ...
- [js] - 关于js的排序sort
js的排序sort并不能一次排序好 function solution(nums){ return nums.sort(sortNumber); } function sortNumber(a, b) ...
- 前端验证用户登陆状态(vue.js)
首先用户需要进行登陆(请求登陆接口),接口请求成功之后后台会返回对应的用户信息(可以把用户信息存放在浏览器缓存中),并且后台会设置浏览器的cookie值(可以在network->header-& ...
- python打包到pypi小结
如果你写了一个python库,想让别人快速使用你的库,最简单的方式就是使用python官方出品的库托管网站pypi了. pypi的全称是Python Package Index,是pyth ...
- python ros 关闭节点
def myhook(): print "shutdown time!" rospy.on_shutdown(myhook) 或 rospy.signal_shutdown(rea ...
- ubuntu16.04上安装Java
1.下载jdk8 登录网址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 选择 ...
- 磁条卡,IC卡,ID卡,信用卡芯片卡,信用卡磁条卡 等等的区别
1.条码卡:该卡卡面上有一串条码,通过扫描枪或者相应的条码读卡器读出该条码卡的卡号.根据条码的不同又分为39码等其它码.条码卡仅仅是一个编号,不存蓄其它内容.特点:价格便宜类似磁卡. 2.磁条卡:类似 ...
- MongoDB(课时18 修改器)
3.4.3.2 修改器(原子操作) 对MongoDB数据库而言,数据的修改会牵扯到内容的变更,结构的变更(包含数组),所以在MongoDB在设计的时候就提供有一系列的修改器的应用,那么像之前使用的“$ ...
- MongoDB(课时8 模运算)
3.4.2.3 求模 模运算使用“$mod”来完成,语法: {$mod : [除数,余数]} 范例:求模 db.students.find({"age" : {"$mod ...