poj3130(半平面交模板)

弄了2天区块链结果还是没弄出什么东西来。。然后回来继续学计算几何。。。

半平面交的模板还是不太好背的 。。玄学公式+双端队列。。emmmmmm

双端队列这东西貌似从斜率优化后就没用到了。。非常生疏。。

算法有2个,一个n^2,一个nlogn。。当然选nlogn。。。

思路是让半平面按极角排序。。然后依次加入队列中排除多余半平面即可。。

细节非常多。。例如:加入队列时要先去队尾再去队首。。最后要先去队首再去队尾。。(坑了我半天。。

然后 cmp那块if判断叉积是否为正时不造为什么老是要丢掉后面的>eps。。。

还有。。就是那个求交点的intersect。。有个玄学公式。。需要用到相似。。这里证明一下。。

原文链接:http://blog.csdn.net/Spectacules/article/details/48397785


如上图所示,对于向量AB和向量CD,其交点为P,现在要求P的坐标。设S1为三角形ACB的面积,S2为三角形ADB的面积,由叉积的性质可得:S1 = cross(A,B,C) / 2,即向量AB和向量AC叉积的一半(注意结果的正负),同理,S2 = cross(A,D,B)。此外,再做三角形ACB和三角形ADB在AB边上的垂线CE和DF,则S1 = |CE| * |AB| / 2,S2 = |DF| * |AB| / 2,而且注意到两个直角三角形CPE和DPF相似,则得到比例关系:|CP| / |PD| = |CE| / |DF|  ,此时由以上五个等式得到:S1 / S2 = |CE| / |DF| = |CP| / |PD|。

设P坐标为(xp,yp),则由S1 / S2 = |CP| / |PD|   ==》 (xc - xp) / (xp - xd) = (yc - yp) / (yp - yd) = S1 / S2  ==》 xp = (S1 * xd + S2 * xc) / (S1 + S2)  , yp = (S1 * yd + S2 * yc) / (S1 + S2)。

然后道理窝是懂。。可是为什么t1、t2非得那样求不可啊。。




#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define eps 1e-8
#define inf 1e9
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define ls T[i<<1]
#define rs T[i<<1|1]
#define op T[i]
#define mid (x+y>>1)
#define NM 10005
#define nm 100498
#define pi 3.141592653
using namespace std;
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return f*x;
}

struct P{
	double x,y;
	P(double x=0,double y=0):x(x),y(y){}
	double operator*(const P&o){return x*o.y-y*o.x;}
	P operator-(const P&o){return P(x-o.x,y-o.y);}
}p[NM];
struct L{P a,b;double k;}l[NM];
int n,tmp[NM],q[NM],qh,qt,m;
bool cmp(int x,int y){
	if(fabs(l[x].k-l[y].k)<eps)return (l[y].b-l[x].a)*(l[x].b-l[x].a)>eps;
	else return l[x].k<l[y].k;
}
void intersect(L x,L y,P&p){
	double t1=(x.b-y.a)*(x.a-y.a),t2=(y.b-x.b)*(x.a-x.b);
	p.x=(y.a.x*t2+y.b.x*t1)/(t1+t2);
	p.y=(y.a.y*t2+y.b.y*t1)/(t1+t2);
}

bool judge(L a,L b,L c){
	P p;
	intersect(b,c,p);
	return (a.b-a.a)*(p-a.a)+eps<0;
}

void solve(){
	sort(tmp+1,tmp+1+n,cmp);m=1;
	inc(i,2,n)if(fabs(l[tmp[i]].k-l[tmp[m]].k)>eps)tmp[++m]=tmp[i];
	mem(q);qh=1;qt=0;
	inc(k,1,m){
		int i=tmp[k];
		while(qh<qt&&judge(l[i],l[q[qt-1]],l[q[qt]]))qt--;
		while(qh<qt&&judge(l[i],l[q[qh+1]],l[q[qh]]))qh++;
		q[++qt]=i;
	}
	while(qh<qt&&judge(l[q[qt]],l[q[qh+1]],l[q[qh]]))qh++;
	while(qh<qt&&judge(l[q[qh]],l[q[qt-1]],l[q[qt]]))qt--;
}

int main(){
	//freopen("data.in","r",stdin);
	while(n=read()){
		inc(i,1,n)p[i].x=read(),p[i].y=read();
		p[n+1]=p[1];
		inc(i,1,n){
			l[i].a=p[i];l[i].b=p[i+1];
			l[i].k=atan2(p[i+1].y-p[i].y,p[i+1].x-p[i].x);
			tmp[i]=i;
		}
		solve();
		//printf("%d %d\n",qh,qt);
		printf("%d\n",qt>qh+1);
	}
	return 0;
}




How I Mathematician Wonder What You Are!
Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 4057 Accepted: 2184

Description

After counting so many stars in the sky in his childhood, Isaac, now an astronomer and a mathematician uses a big astronomical telescope and lets his image processing program count stars. The hardest part of the program is to judge if shining object in the sky is really a star. As a mathematician, the only way he knows is to apply a mathematical definition ofstars.

The mathematical definition of a star shape is as follows: A planar shape F is star-shaped if and only if there is a point C ∈ F such that, for any point P ∈F, the line segment CP is contained in F. Such a point C is called acenter of F. To get accustomed to the definition let’s see some examples below.

The first two are what you would normally call stars. According to the above definition, however, all shapes in the first row are star-shaped. The two in the second row are not. For each star shape, a center is indicated with a dot. Note that a star shape in general has infinitely many centers. Fore Example, for the third quadrangular shape, all points in it are centers.

Your job is to write a program that tells whether a given polygonal shape is star-shaped or not.

Input

The input is a sequence of datasets followed by a line containing a single zero. Each dataset specifies a polygon, and is formatted as follows.

n 
x1y1
x2y2

xnyn

The first line is the number of vertices, n, which satisfies 4 ≤ n ≤ 50. Subsequent n lines are the x- and y-coordinates of then vertices. They are integers and satisfy 0 ≤ xi ≤ 10000 and 0 ≤yi ≤ 10000 (i = 1, …, n). Line segments (xi,yi)–(xi + 1, yi + 1) (i = 1, …,n − 1) and the line segment (xn, yn)–(x1,y1) form the border of the polygon in the counterclockwise order. That is, these line segments see the inside of the polygon in the left of their directions.

You may assume that the polygon is simple, that is, its border never crosses or touches itself. You may assume assume that no three edges of the polygon meet at a single point even when they are infinitely extended.

Output

For each dataset, output “1” if the polygon is star-shaped and “0” otherwise. Each number must be in a separate line and the line should not contain any other characters.

Sample Input

6 
66 13 
96 61 
76 98 
13 94 
4 0 
45 68 
8 
27 21 
55 14 
93 12 
56 95 
15 48 
38 46 
51 65 
64 31 
0

Sample Output

1
0

Source

[Submit]   [Go Back]   [Status]   [Discuss]


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值