您的位置:首页 > 编程语言

计算几何题目推荐第一期AC代码

2010-12-12 12:09 190 查看
很多题,很多代码:

一、点,线,面,形基本关系,点积叉积的理解
/*poj2318toys*/
//判断箱子每一个块内有多少个玩具,可以用叉积的性质找到玩具的位置,过程采用二分查找。
#include <cstdio>
#include <cstring>
using namespace std;
#define EPS 1e-8
const int MAXN = 5010;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};

inline double difcross(Point p1,Point p0,Point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
struct pi{
Point first;
Point second;
}PII[MAXN];

int mark[MAXN];
int n,m;
double x1,y1,x2,y2;
int main(){
int k = 0;
while(scanf("%d",&n) != EOF){
if(n == 0)break;
k ++;
if(k != 1)putchar('\n');
scanf("%d%lf%lf%lf%lf",&m,&x1,&y1,&x2,&y2);
memset(mark,0,sizeof(mark));
double ui,li;
for(int i = 1; i <= n; ++i){
scanf("%lf%lf",&ui,&li);
PII[i].first = Point(ui,y1);
PII[i].second = Point(li,y2);
}
Point toy;
for(int i = 0; i < m; ++i){
toy.input();
int low = 1,high = n,mid;
while(low <= high){
mid = (low + high)/2;
if(difcross(toy,PII[mid].second,PII[mid].first) > 0)
low = mid + 1;
else high = mid - 1;
}
//printf("low = %d  high = %d mid = %d\n",low,high,mid);
mark[high] ++;
}

for(int i = 0; i <= n; ++i)
printf("%d: %d\n",i,mark[i]);

}
}

//另外,poj2398Toy Storage与此题雷同,不再重复

/*POJ3304 Segments*/
//  判断线段与直线相交
#include<iostream>
#include<cmath>
using namespace std;
#define ESP 1e-8
inline int dblcmp(double d){
if(fabs(d) < ESP)return 0;
else return d > 0 ? 1 : -1;
}
struct Point{
double x,y;
};
struct Seg{
Point a,b;
};
struct xlg{
double x,y;
};
inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline double difpro(Point a,Point b,Point c){
double x1 = b.x - a.x,
y1 = b.y - a.y,
x2 = c.x - a.x,
y2 = c.y - a.y;
return (x1*y2 - x2*y1);
}
inline int seg_line_intersect(Seg seg, Point l1,Point l2){
if(dblcmp(difpro(l1,seg.a,l2)*difpro(l1,seg.b,l2)) <= 0)return 1;
return 0;
}
const int maxn = 110;
Seg seg[maxn];
int n;
inline bool cal(Point l1,Point l2){
for(int i = 0; i < n; i++){
if(!seg_line_intersect(seg[i],l1,l2))
return 0;
}
return 1;
}
int main(){
int cas,i,j;
double x,y;
scanf("%d",&cas);
while(cas--){
int flag = 0;
scanf("%d",&n);
for(i = 0; i < n; i++)
scanf("%lf%lf%lf%lf",&seg[i].a.x,&seg[i].a.y,&seg[i].b.x,&seg[i].b.y);
for(i = 0; i < n; i++){
for(j = i; j < n; j++){
if(dblcmp(pdis(seg[i].a,seg[j].a)) > 0){
if(cal(seg[i].a,seg[j].a)){
flag = 1;break;
}
}
if(dblcmp(pdis(seg[i].a,seg[j].b)) > 0){
if(cal(seg[i].a,seg[j].b)){
flag = 1;break;
}
}
if(dblcmp(pdis(seg[i].b,seg[j].a)) > 0){
if(cal(seg[i].b,seg[j].a)){
flag = 1;break;
}
}
if(dblcmp(pdis(seg[i].b,seg[j].b)) > 0){
if(cal(seg[i].b,seg[j].b)){
flag = 1;break;
}
}
}
}
if(flag)printf("Yes!\n");
else printf("No!\n");
}
return 0;
}

/*poj1269Intersecting Lines*/
//直线相交判断,注意是一条直线(共线)的情况
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define feq(a,b) (fabs((a)-(b))<EPS)
#define EPS 1e-8
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};

struct Line{
double a,b,c;
};

inline void getline(Point p1,Point p2,Line &l){
l.a = p2.y - p1.y;
l.b = p1.x - p2.x;
l.c = p1.y*p2.x - p1.x*p2.y;
if (l.a < 0) l.a *= -1,l.b *= -1,l.c *= -1;
}

inline int line_intersect(Line l1,Line l2,Point &ans){
double d=l1.a*l2.b-l2.a*l1.b;
if (feq(d, 0)) return 0;
ans.x = (l2.c*l1.b-l1.c*l2.b)/d;
ans.y = (l2.a*l1.c-l1.a*l2.c)/d;
return 1;
}

int N;

int main(){
scanf("%d",&N);
Point p3,p4,q1,q2,ans;
Line l1,l2;
puts("INTERSECTING LINES OUTPUT");
while(N --){
p3.input();
p4.input();
getline(p3,p4,l1);

q1.input();
q2.input();
getline(q1,q2,l2);

int tmp = line_intersect(l1,l2,ans);
if(tmp == 0){
if(feq(l1.a*l2.b,l2.a*l1.b) && feq(l1.a*l2.c,l2.a*l1.c) && feq(l1.b*l2.c,l2.b*l1.c)){
printf("LINE\n");
}
else printf("NONE\n");
}
else printf("POINT %.2lf %.2lf\n",ans.x,ans.y);
}
puts("END OF OUTPUT");
return 0;
}

/*poj1556The Doors*/
// 利用的计算几何并不多(判断线段相交),建图比较繁琐,然后用dijkstra求最短路即可
#include <cstdio>
#include <cstring>
#include<cmath>
using namespace std;
#define inf 99999999
const int maxn = 200;
struct Point {
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
};
double cross(Point a,Point a1,Point a2){
return (a1.x - a.x)*(a2.y - a.y)-(a2.x - a.x)*(a1.y - a.y);
}
double dist[maxn][maxn];

double pdis(Point a,Point b){
return sqrt( (a.x - b.x)*(a.x - b.x)+(a.y - b.y)*(a.y - b.y) );
}
int isintersect(Point a1,Point a2,Point b1,Point b2){
if(cross(a1,a2,b1)*cross(a1,a2,b2) < 0 && cross(b1,b2,a1)*cross(b1,b2,a2) < 0)return 1;
return 0;
}
Point points[maxn];
int main(){
int n,i,j;
while(scanf("%d",&n) != EOF){
if(n == -1)break;
int cnt = 1;
double num,x[maxn];
points[0] = Point(0,5);
for(i = 1; i <= n; i ++){
scanf("%lf",&x[i]);
for(j = 0; j < 4; j++){
scanf("%lf",&num);
points[cnt++] = Point(x[i],num);
}
}

points[cnt] = Point(10,5);
int ti,fi,tj,fj;

for(i = 0; i < maxn; i++){
for(j = 0; j < maxn ; j++){
dist[i][j] = inf;
}
}
for(i = 0; i < maxn; i++)dist[i][i] = 0;
for(i = 0; i <= cnt; i++){
for(j = i+1; j <= cnt; j++){
if(points[i].x == points[j].x){
continue;
}
if(i%4 == 0)ti = i/4;
else ti = i/4+1;

if(j%4 == 0)tj = j/4;
else tj = j/4+1;
int flag = 1;
for(int k= ti + 1; k < tj; k++){
Point pk1 = Point(x[k],0);
Point pk2 = Point(x[k],10);
if(isintersect(points[i],points[j],pk1,points[4*(k-1)+1])){
flag = 0;break;
}
if(isintersect(points[i],points[j],points[4*(k-1)+2],points[4*(k-1)+3])){
flag = 0;break;
}
if(isintersect(points[i],points[j],points[4*(k-1)+4],pk2)){
flag = 0;
break;
}
}
if(flag){
double tm = pdis(points[i],points[j]);
dist[i][j] = tm;
dist[j][i] = tm;
}
}
}
cnt++;
int mark[maxn];
double  dis[maxn];
for(i = 0; i < cnt; i++){
dis[i] = dist[0][i];
}
memset(mark,0,sizeof(mark));
mark[0] = 1;
for(i = 0; i < cnt - 1; i++){
double  mi = inf;
int u = 0;
for(j = 0; j < cnt; j++){
if(!mark[j] && dis[j] < mi){
mi = dis[j];
u = j;
}
}
mark[u] = 1;
for(j = 0; j < cnt; j++){
if(!mark[j] && dis[u] + dist[u][j] < dis[j]){
dis[j] = dis[u] + dist[u][j];
}
}
}
printf("%.2lf\n",dis[cnt-1]);
}
return 0;
}

/*poj2653Pick-up sticks*/
//赤裸裸的线段求交
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
using namespace std;
#define EPS 1e-6
#define INF 1000000000
const int maxn = 100000;
struct Point {
double x,y;
Point(){};
Point(double _x,double _y):x(_x),y(_y){}
void in(){
scanf("%lf%lf",&x,&y);
}
};

double min(double a,double b){return a > b ? b : a;}
double max(double a,double b){return a > b ? a : b;}

double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double cproduct(Point a,Point a1,Point a2){
return (a1.x - a.x)*(a2.y - a.y) -(a2.x - a.x)*(a1.y - a.y);
}

double dproduct(Point a,Point a1,Point a2){
return (a1.x-a.x)*(a1.y-a.y) + (a2.x-a.x)*(a2.y-a.y);
}

bool isIntersected(Point s1, Point e1, Point s2, Point e2) {
return ( max(s1.x, e1.x) >= min(s2.x, e2.x) )
& ( max(s2.x, e2.x) >= min(s1.x, e1.x) )
&( max(s1.y, e1.y) >= min(s2.y, e2.y) )
& ( max(s2.y, e2.y) >= min(s1.y, e1.y) )
& ( cproduct(s2, e1, s1) * cproduct(e1, e2, s1)>0) //>0规范性相交且不包括重合;
& ( cproduct(s1, e2, s2) * cproduct(e2, e1, s2)>0); //>=0包括规范性和非规范性相交且包括重合;
}
struct seg{
Point a,b;
};
int main(){
int n;
seg segs[maxn];
while(scanf("%d",&n)!=EOF){
if(n == 0)break;
for(int i = 0; i < n; i++){
scanf("%lf%lf%lf%lf",&segs[i].a.x,&segs[i].a.y,&segs[i].b.x,&segs[i].b.y);
}
int mark[maxn];
memset(mark,0,sizeof(mark));
for(int i = 0; i < n; i++){
for(int j = i+1; j < n; j++){
if(isIntersected(segs[i].a,segs[i].b,segs[j].a,segs[j].b) != 0){
mark[i] = 1;
break;
}
}
}

printf("Top sticks: ");
int ans[maxn];
int q = -1;
for(int i =  0; i < n; i++){
if(mark[i] == 0)ans[++q] = i+1;
}
for(int i = 0; i < q; i++){
printf("%d, ",ans[i]);
}
printf("%d.\n",ans[q]);
}
return 0;
}

/*POJ 1066 Treasure Hunt*/

//线段相交判断

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define ESP 1e-8
int dblcmp(double d){
if(fabs(d) < ESP)return 0;
else return d > 0 ? 1 : -1;
}
struct Point{
double x,y;
};
struct Seg{
Point a,b;
};
struct xlg{
double x,y;
};
double difpro(xlg a,xlg b){
return (a.x*b.y-a.y*b.x);
}
xlg getxlg(Point a,Point b){
xlg tmp;
tmp.x = b.x - a.x;
tmp.y = b.y - a.y;
return tmp;
}
int seg_line_intersect(Point a,Point b, Point l1,Point l2)
{
xlg v1 = getxlg(l1,a),
v2 = getxlg(l1,l2),
v3 = getxlg(l1,b);
if(dblcmp(difpro(v1,v2)*difpro(v3,v2)) < 0)return 1;
return 0;
}
const int maxn = 35;
Seg segs[maxn];
Point dest;
int n;
int main(){
double  y0[maxn],x0[maxn],y100[maxn],x100[maxn];

while(scanf("%d",&n)!=EOF){
memset(y0,0,sizeof(y0));
memset(x0,0,sizeof(x0));
memset(y100,0,sizeof(y100));
memset(x100,0,sizeof(x100));
int qy0 = 1,qx0 = 1, qx100 = 1,qy100 = 1;

for(int i = 0; i < n; i++){
scanf("%lf%lf%lf%lf",&segs[i].a.x,&segs[i].a.y,&segs[i].b.x,&segs[i].b.y);
if(segs[i].a.x == 0)x0[qx0++] = segs[i].a.y;
if(segs[i].a.x == 100)x100[qx100++] = segs[i].a.y;
if(segs[i].a.y == 0)y0[qy0++] = segs[i].a.x;
if(segs[i].a.y == 100)y100[qy100++] = segs[i].a.x;

if(segs[i].b.x == 0)x0[qx0++] = segs[i].b.y;
if(segs[i].b.x == 100)x100[qx100++] = segs[i].b.y;
if(segs[i].b.y == 0)y0[qy0++] = segs[i].b.x;
if(segs[i].b.y == 100)y100[qy100++] = segs[i].b.x;
}
int cnt,mi = 9999999;
scanf("%lf%lf",&dest.x,&dest.y);
if(n == 0){
printf("Number of doors = 1\n");
continue;
}
sort(x0,x0+qx0);
sort(y0,y0+qy0);
sort(x100,x100+qx100);
sort(y100,y100+qy100);
x0[0] = 0;x0[qx0] = 100;
y0[0] = 0;y0[qy0] = 100;
x100[0] = 0;x100[qx100] = 100;
y100[0] = 0; y100[qy100] = 100;
for(int i = 1; i <= qx0; i++){
cnt = 1;
Point t;
t.y = (x0[i-1]+x0[i])/2;
t.x = 0;
for(int j = 0; j < n; j++){
if(seg_line_intersect(t,dest,segs[j].a,segs[j].b))cnt++;
}
if(mi > cnt)mi = cnt;
}

for(int i = 1; i <= qx100; i++){
cnt = 1;
Point t;
t.y = (x100[i-1]+x100[i])/2;
t.x = 100;
for(int j = 0; j < n; j++){
if(seg_line_intersect(t,dest,segs[j].a,segs[j].b))cnt++;
}
if(mi > cnt)mi = cnt;
}

for(int i = 1; i <= qy0; i++){
cnt = 1;
Point t;
t.x = (y0[i-1]+y0[i])/2;
t.y = 0;
for(int j = 0; j < n; j++){
if(seg_line_intersect(t,dest,segs[j].a,segs[j].b))cnt++;
}
if(mi > cnt)mi = cnt;
}

for(int i = 1; i <= qy100; i++){
cnt = 1;
Point t;
t.x = (y100[i-1]+y100[i])/2;
t.y = 100;
for(int j = 0; j < n; j++){
if(seg_line_intersect(t,dest,segs[j].a,segs[j].b))cnt++;
}
if(mi > cnt)mi = cnt;
}
printf("Number of doors = %d\n",mi);
}
return 0;
}

/*POJ 1410 Intersection*/
//判断线段是否与矩形相交,分别判断线段是否与矩形的四条边相交,另外注意一下整个线段在矩形中即可,还有这题描述不清,看discuss吧;
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define EPS 1e-8
#define sqr(a) ( (a*a) )
#define max(a,b) ((a)>(b) ? (a) : (b))
#define min(a,b) ((a)<(b) ? (a) : (b))
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};
struct Segment{
Point a,b;
Segment(){}
Segment(Point _a,Point _b):a(_a),b(_b){}
};

inline double difcross(Point p0,Point p1,Point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
inline bool SegIntersect(Segment s1,Segment s2)
{
double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x);
double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x);
double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y);
double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y);
return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&&
fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&&
fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) &&
fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y);
}
Point s,t,p1,p2,p3,p4;
Segment s1,s2;
int main(){
int n;
scanf("%d",&n);
while(n --){
s.input();
t.input();
p1.input();
p3.input();
double maxx = max(p1.x,p3.x);
double minx = min(p1.x,p3.x);
double maxy = max(p1.y,p3.y);
double miny = min(p1.y,p3.y);
p1 = Point(minx,maxy);
p3 = Point(maxx,miny);

p2 = Point(p1.x,p3.y);
p4 = Point(p3.x,p1.y);
s1 = Segment(s,t);
maxx = max(s.x,t.x);
minx = min(s.x,t.x);
maxy = max(s.y,t.y);
miny = min(s.y,t.y);
bool flag = 0;
if(minx > p1.x + EPS && maxx +EPS < p3.x && maxy +EPS < p1.y
&& miny > p3.y+EPS)flag = 1;
s2 = Segment(p1,p2);
if(SegIntersect(s1,s2))flag = 1;
s2 = Segment(p2,p3);
if(SegIntersect(s1,s2))flag = 1;
s2 = Segment(p3,p4);
if(SegIntersect(s1,s2))flag = 1;
s2 = Segment(p4,p1);
if(SegIntersect(s1,s2))flag = 1;
if(!flag)puts("F");
else puts("T");
}
return 0;
}

/*POJ 1696 Space Ant*/
//非常好的题目,知道怎么做的话就是个水题,根据Graham求凸包的思想,每次找到最左下的那个点即可(每次排序的基准点改变)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define EPS 1e-8
#define feq(a,b) (fabs((a)-(b))<EPS)
#define fbg(a,b) ((a) > EPS+(b))
#define dis(a, b) ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))
#define dist(p1, p2, a) (fabs(difcross(p1, a, p2)/sqrt(dis(p1,p2))))
const int MAXN = 55;
struct Point{
double x,y;
int id;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%d%lf%lf",&id,&x,&y);
}
};
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
Point p[MAXN];
Point p0;
int anstop,n,ans[MAXN];
inline int cmp(Point a, Point b)
{
double k = difcross(p0, a, b);
if(feq(k,0) && fbg(pdis(a, p0) , pdis(b, p0)))return 1;
else if( k > EPS ) return 1;
return 0;
}
int main(){
int cas;
scanf("%d",&cas);
while(cas --){
scanf("%d",&n);
for(int i = 0; i < n ; ++i){
p[i].input();
if(p[i].y < p[0].y)
swap(p[0],p[i]);
}
anstop = 0;
int cur = 0;
p0 = p[cur];
ans[anstop++] = p[cur++].id;
for(int i = 0; i < n - 1; ++i){

sort(p+cur,p+n,cmp);
p0 = p[cur];
ans[anstop++] = p[cur++].id;
}
printf("%d",anstop);
for(int i = 0; i < anstop; ++i){
printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}

poj3347Kadj Squares
//非常没素质的一道讨论题,不想写。

/*POJ 2826An Easy Problem?!*/
/* 重点不在easy problem,在于后面的两个标点符号。
*哥见的easy problem多了,大都很难,鄙视出题人!这题情况很多,要慢慢讨论:
*discuss有一个比较好的:
*找出交点P
*统计4个点有多少个比p点高,要有两个点a和b才行,比较矮的那个交点a向上的垂直射线是否与高的那点b所在的线是否相交
*不想交就用叉积求面积。
*/

#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define max(a,b) ((a)>(b) ? (a) : (b))
#define min(a,b) ((a)<(b) ? (a) : (b))
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
#define EPS 1e-8
#define feq(a,b) (fabs((a)-(b))<EPS)
#define fbg(a,b) ((a) > EPS+(b))
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};
struct Segment{
Point a,b;
Segment(){}
Segment(Point _a,Point _b):a(_a),b(_b){}
};

struct Line{
double a,b,c;
Line(){}
Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){}
};
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}

inline void getline(Point p1,Point p2,Line &l){
l.a = p2.y - p1.y;
l.b = p1.x - p2.x;
l.c = p1.y*p2.x - p1.x*p2.y;
if (l.a < 0) l.a *= -1,l.b *= -1,l.c *= -1;
}
inline bool line_intersect(Line l1,Line l2,Point &p)
{
double d=l1.a*l2.b-l2.a*l1.b;
if (feq(d, 0)) return 0;
p.x = (l2.c*l1.b-l1.c*l2.b)/d;
p.y = (l2.a*l1.c-l1.a*l2.c)/d;
return true;
}

inline bool SegIntersect(Segment s1,Segment s2)
{
if (fabs(difcross(s1.a, s2.a, s2.b)) < EPS &&
fabs(difcross(s1.b, s2.a, s2.b)) < EPS) return 0;
double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x);
double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x);
double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y);
double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y);
return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&&
fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&&
fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) &&
fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y);
}
inline double trarea(Point a,Point b,Point c){
return   fabs(difcross(a,b,c))/2.0;
}

int main(){
int n;
scanf("%d",&n);
Point a,b,c,d,cross;
while(n --){
double ans;
a.input();
b.input();
c.input();
d.input();
double y1 = max(a.y,b.y);
double y2 = max(c.y,d.y);
Segment s1,s2;
if(fbg(y1,y2)){
s1 = Segment(c,d);
s2 = Segment(a,b);
}
else{
s1 = Segment(a,b);
s2 = Segment(c,d);
}
if(!SegIntersect(s1,s2)){
printf("0.00\n");
continue;
}
Line l1,l2;
getline(a,b,l1);
getline(c,d,l2);
line_intersect(l1,l2,cross);
int cnt = 0;
if(fbg(a.y,cross.y))cnt ++;
if(fbg(b.y,cross.y))cnt ++;
if(fbg(c.y,cross.y))cnt ++;
if(fbg(d.y,cross.y))cnt ++;
if(cnt < 2){
printf("0.00\n");
continue;
}
Point tmp = fbg(s1.a.y,s1.b.y) ? s1.a : s1.b;
Line l3 = Line(0,1,-tmp.y);
Point pp;
getline(s2.a,s2.b,l2);
line_intersect(l2,l3,pp);
Segment s3 = Segment(tmp,Point(tmp.x,1e100));
if(SegIntersect(s2,s3)){
printf("0.00\n");
continue;
}
ans = trarea(tmp,cross,pp);
printf("%.2lf\n",ans);
}
return 0;
}

/*POJ 1039 Pipe*/

//恶心的枚举,容易错,注意叉乘的性质,精度1e-3或者不要都可以
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

#define EPS 1e-6
#define max(a,b) ((a)>(b) ? (a) : (b))
#define min(a,b) ((a)<(b) ? (a) : (b))
#define a2r(a) (((a)*PI)/180.0)//角度到弧度
#define r2a(a) (((a)/PI)*180.0)//弧度到角度
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
const int MAXN = 30;

struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};
Point psa[MAXN],psb[MAXN];
struct Segment{
Point a,b;
Segment(){}
Segment(Point _a,Point _b):a(_a),b(_b){}
};

struct Line{
double a,b,c;
Line(){}
Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){}
};

inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
inline int SegLineIntersect(Point s1,Point s2,Point e1,Point e2){
if(difcross(e1,e2,s1)*difcross(e1,e2,s2) <= 0)return 1;
return 0;
}

inline void getline(Point p1,Point p2,Line &l){
l.a = p2.y - p1.y;
l.b = p1.x - p2.x;
l.c = p1.y*p2.x - p1.x*p2.y;
if (l.a < 0) l.a *= -1,l.b *= -1,l.c *= -1;
}
inline bool line_intersect(Line l1,Line l2,Point &p)
{
double d=l1.a*l2.b-l2.a*l1.b;
if (feq(d, 0)) return 0;
p.x = (l2.c*l1.b-l1.c*l2.b)/d;
p.y = (l2.a*l1.c-l1.a*l2.c)/d;
return true;
}

int n;
int main(){
while(scanf("%d",&n) != EOF){
if(n == 0)break;
double ans = -1e100;
for(int i = 0; i < n; ++i){
psa[i].input();
psb[i] = Point(psa[i].x,psa[i].y-1);
}
Line l1,l2,l3,l;
Point cross;
Segment s1,s2;
for(int i = 0; i < n; ++i){
for(int j = 0; j < n; ++j){
if(i == j)continue;
int k = max(i,j);
int tag;
getline(psa[i],psb[j],l);
for(tag = 0; tag < n; tag++){
if(fsmeq(difcross(psa[i],psa[tag],psb[j])*
difcross(psa[i],psb[tag],psb[j]),0))
continue;
else break;
}
if(tag < k)continue;
if(tag == n){
ans = psa[n-1].x;
break;
}
if(SegLineIntersect(psa[tag-1],psa[tag],psa[i],psb[j])){
getline(psa[tag-1],psa[tag],l1);
line_intersect(l1,l,cross);
if(ans < cross.x)ans = cross.x;
}
if(SegLineIntersect(psb[tag-1],psb[tag],psa[i],psb[j])){
getline(psb[tag-1],psb[tag],l1);
line_intersect(l1,l,cross);
if(ans < cross.x)ans = cross.x;
}

}
}
if(ans == psa[n-1].x)puts("Through all the pipe.");

else  printf("%.2lf\n",ans);
}
return 0;
}

/*POJ 3449 Geometric Shapes*/
//堪称屎上第一屎的题目,输入输出都很烦,判断几何体是否相交
///没见过输入输出这么没素质的,光输入输出处理了100多行,没办法,谁让咱不是出题的。
//其实就利用了一个线段相交判断,还有一个就是已知正方形的对角线上两个点,求出另外两个点的坐标
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define EPS 1e-16
#define max(a,b) ((a)>(b) ? (a) : (b))
#define min(a,b) ((a)<(b) ? (a) : (b))

#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b

const int MAXN = 30;

struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};
struct Segment{
Point a,b;
Segment(){}
Segment(Point _a,Point _b):a(_a),b(_b){}
};
struct Thing{
char tag;
Point p[25];
char op[20];
int n;

inline int input(){
scanf(" %c",&tag);
if(tag == '.')return -1;
if(tag == '-')return 0;
scanf(" %s",op);
if(!strcmp(op,"square")){
n = 4;
scanf(" (%lf,%lf)",&p[1].x,&p[1].y);
scanf(" (%lf,%lf)",&p[3].x,&p[3].y);
Point b, d;
double x,y,mx, my;
mx = (p[1].x+p[3].x)/2.0, my = (p[1].y+p[3].y)/2.0;
x = p[1].x - mx;    y = p[1].y - my;
p[2].x = -y + mx;   p[2].y = x + my;
p[4] = Point(p[1].x+p[3].x-p[2].x,p[1].y+p[3].y-p[2].y);
p[0] = p[4];
}
else if(!strcmp(op,"triangle")){
n = 3;
scanf(" (%lf,%lf)",&p[1].x,&p[1].y);
scanf(" (%lf,%lf)",&p[2].x,&p[2].y);
scanf(" (%lf,%lf)",&p[3].x,&p[3].y);
p[0] = p[3];
}

else if(!strcmp(op,"line")) {
n = 2;
scanf(" (%lf,%lf)",&p[1].x,&p[1].y);
scanf(" (%lf,%lf)",&p[2].x,&p[2].y);
p[0] = p[2];
}
else if(!strcmp(op,"rectangle")){
n = 4;
scanf(" (%lf,%lf)",&p[1].x,&p[1].y);
scanf(" (%lf,%lf)",&p[2].x,&p[2].y);
scanf(" (%lf,%lf)",&p[3].x,&p[3].y);
p[4] = Point(p[1].x+p[3].x-p[2].x,p[1].y+p[3].y-p[2].y);
p[0] = p[4];

}
else if(!strcmp(op,"polygon")){
scanf("%d",&n);
for(int i = 1; i <= n; ++i)
scanf(" (%lf,%lf)",&p[i].x,&p[i].y);
p[0] = p
;
}
return 1;
}
};
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}

inline bool SegIntersect(Segment s1,Segment s2)
{

double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x);
double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x);
double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y);
double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y);
return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&&
fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&&
fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) &&
fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y);
}

inline bool Intersect(Thing a,Thing b){
int flag = 0;
Segment s1,s2;
for(int i = 0; i < a.n; ++i){
for(int j = 0; j < b.n; ++j){
s1 = Segment(a.p[i],a.p[i+1]);
s2 = Segment(b.p[j],b.p[j+1]);
if(SegIntersect(s1,s2))return 1;
}
}
return 0;
}
inline int cmp(Thing a,Thing b){
return a.tag < b.tag;
}

Thing things[MAXN];
char ans[MAXN];
int main(){
int top;
Thing tmp;
while(tmp.input() != -1){
if(tmp.tag == '-')continue;
top = 0;
things[top] = tmp;
while(tmp.input() != 0){
things[++top] = tmp;
}
top ++;

sort(things,things+top,cmp);
for(int i = 0; i < top; ++i){
int t = 0;
printf("%c ",things[i].tag);

for(int j = 0; j < top; ++j){
if(i == j)continue;
if(Intersect(things[i],things[j])){
ans[t++] = things[j].tag;
}
}
if(t == 0)
puts("has no intersections");
else if(t == 1)
printf("intersects with %c\n",ans[0]);
else if(t == 2)
printf("intersects with %c and %c\n",ans[0],ans[1]);
else{
printf("intersects with ");
for(int j = 0; j < t - 1; ++j)
printf("%c, ",ans[j]);
printf("and %c\n",ans[t-1]);
}
}
puts("");
}
return 0;
}

/*POJ 1584 A Round Peg in a Ground Hole*/
//这题用的东西很多,包括点到直线距离,圆与多边形相交(圆在多边形内判断),判断多边形是否为凸多边形
/*
关于圆在多边形内判断,要先判断圆心是否在多边形内,这个我是套的点在多边形内的模板,对于凸多边形,有一种特定的方法去判断(这样的话代码长度会大大缩短):点在已知凸包内(包括三点共线)====》其对于所有边的叉乘同大于等于0或小于等于0;本人代码仅供个人观赏。一般人看不懂。
*/
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define INF 1e100
#define EPS 1e-8
#define PI acos(-1.0)
#define max(a,b) ((a)>(b) ? (a) : (b))
#define min(a,b) ((a)<(b) ? (a) : (b))
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
const int MAXN = 100010;

struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};
struct Segment{
Point a,b;
Segment(){}
Segment(Point _a,Point _b):a(_a),b(_b){}
};

struct Circle{
Point cer;
double radious;
Circle(){}
Circle(Point _cer,double _radious):cer(_cer),radious(_radious){}
void input(){
scanf("%lf",&radious);
cer.input();
}
};
struct Line{
double a,b,c;
Line(){}
Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){}
};
inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
inline double p2seg(Point a,Point p1,Point p2){
return fabs(difcross(a,p1,p2))/pdis(p1,p2);
}
inline bool SegIntersect(Segment s1,Segment s2)
{
if (fabs(difcross(s1.a, s2.a, s2.b)) < EPS &&
fabs(difcross(s1.b, s2.a, s2.b)) < EPS) return 0;
double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x);
double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x);
double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y);
double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y);
return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&&
fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&&
fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) &&
fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y);
}

inline int PonSeg(Point a,Point p1,Point p2){
if(fabs(difcross(a,p1,p2)) <= EPS && a.x >= min(p1.x,p2.x)
&& a.x <= max(p1.x,p2.x)
&& a.y >= min(p1.y,p2.y) && a.y <= max(p1.y,p2.y))
return 1;
return 0;
}

#define on_s2r(p, s) (feq(p.y, s.y) && fbgeq(p.x, s.x))
inline int p_in_polygon(Point a,Point p[],int np)
{  //点a是否在点数为np的多边形内
int count = 0;
Segment s,ps;
ps.a = a,ps.b = a;
ps.b.x = INF;
for(int i = 0;i < np;i++){
s.a = p[i];
if(i + 1 < np)s.b = p[i+1];
else s.b = p[0];
if (s.a.y > s.b.y)swap(s.a,s.b);
if (PonSeg(a,s.a,s.b))return 2;
if (!feq(s.a.y, s.b.y)){
if (on_s2r(s.b, a)) count++;
else if (!on_s2r(s.a, a) && SegIntersect(s,ps))count++;
}
}
if (count%2)return 1;
return 0;
}
/*对于凸多边形,还可以这样判断(代替普通的射线法求点在多边形内):
inline int p_in_polygon(Point a,Point p[],int np)
{
p[np] = p[0];
p[np+1] = p[1];
for(int i = 0; i < np; ++i){
double tmp = difcross(a,p[i],p[i+1])*difcross(a,p[i+1],p[i+2]);
if(tmp < -EPS)return 0;
}
return 1;
}

*/

inline bool cir_in_polygon(Circle a,Point ps[],int np){
int ans = p_in_polygon(a.cer,ps,np);
if(ans == 0)return 0;
double mi = INF;
ps[np] = ps[0];
for(int i = 0; i < np; ++i){
double t = p2seg(a.cer,ps[i],ps[i+1]);

mi = min(mi,t);
}
if(fbgeq(mi,a.radious))return 1;
return 0;
}

inline bool isTu(Point ps[],int n){
ps
= ps[0];
for(int i = 0; i < n; ++i){
for(int j = 0; j < n; ++j){
double tmp = difcross(ps[i],ps[i+1],ps[j])*difcross(ps[i],ps[i+1],ps[j+1]);
if(tmp < -EPS)return 0;
}
}
return 1;
}

int main(){
Circle a;
Point ps[MAXN];
int n;
while(scanf("%d",&n) != EOF){
if(n < 3)break;
a.input();
for(int i = 0; i < n; ++i)ps[i].input();
if(!isTu(ps,n)){
puts("HOLE IS ILL-FORMED");
continue;
}
if(cir_in_polygon(a,ps,n)){
puts("PEG WILL FIT");
continue;
}
puts("PEG WILL NOT FIT");

}
return 0;
}

/*POJ 2074 Line of Sight*/
//鄙视好多trick的题,特别是有trick的计算几何题,障碍物可能在房子以上或者线以下,然后注意直线和线段不相交的时候的情况
//有好几种 ,我的代码很长,应该是方法不好,因为我先求的是被覆盖的区间然后处理的
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;

#define EPS 1e-8
#define max(a,b) ( (a) > (b) ? (a) : (b) )
#define min(a,b) ( (a) < (b) ? (a) : (b) )
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
const int MAXN = 1000;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};
struct Line{
double a,b,c;
Line(){}
Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){}
};
Line tmp,line;
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
inline void getline(Point p1,Point p2,Line &l){
l.a = p2.y - p1.y;
l.b = p1.x - p2.x;
l.c = p1.y*p2.x - p1.x*p2.y;
if (l.a < 0) l.a *= -1,l.b *= -1,l.c *= -1;
}
inline bool line_intersect(Line l1,Line l2,Point &p)
{
double d=l1.a*l2.b-l2.a*l1.b;
if (feq(d, 0)) return 0;
p.x = (l2.c*l1.b-l1.c*l2.b)/d;
p.y = (l2.a*l1.c-l1.a*l2.c)/d;
return true;
}
struct Ans{
double x1,x2;
};
Ans ans[MAXN];
inline int cmp(Ans a,Ans b){
return a.x1 < b.x1;
}
int main(){
double a,b,c;
Point ha,hb;
Point la,lb;
while(scanf("%lf%lf%lf",&a,&b,&c) != EOF){
if(a == 0 && b == 0 && c == 0)break;
ha = Point(a,c);
hb = Point(b,c);
scanf("%lf%lf%lf",&a,&b,&c);
la = Point(a,c);
lb = Point(b,c);
getline(la,lb,line);

int n;
Point ta,tb,tt;
scanf("%d",&n);
bool flag = 0;
for(int i = 0; i < n; ++i){//直接求的直线与直线相交
scanf("%lf%lf%lf",&a,&b,&c);
if(fsmeq(ha.y,c)||fsmeq(c,la.y)){
ans[i].x1 = ans[i].x2 = lb.x;
continue;
}
ta = Point(a,c);
tb = Point(b,c);
getline(ha,tb,tmp);
line_intersect(tmp,line,tt);
ans[i].x2 = tt.x;

getline(hb,ta,tmp);
line_intersect(tmp,line,tt);
ans[i].x1 = tt.x;

}
sort(ans,ans+n,cmp);
double cur = la.x;
double res = 0;
int t = 0;
while(t < n){
if(fsm(res,ans[t].x1-cur))
res = ans[t].x1-cur;
cur = max(cur,ans[t].x2);
t ++;
}
if(fsm(res,lb.x-cur))res = lb.x-cur;
if(feq(res,0))printf("No View\n");
else printf("%.2lf\n",res);
}
}

二、凸包问题

/*POJ 1113 Wall*/
//裸的凸包,可以做模板
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))
#define EPS 1e-8
#define PI acos(-1.0)
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b

const int MAXN = 1000;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};

inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
Point p0;
int top,n,graham[MAXN];
Point points[MAXN];
inline int cmp(Point a, Point b)
{
double k = difcross(p0, a, b);
if(feq(k,0) && fbg(pdis(a, p0) , pdis(b, p0)))return 1;
else if( k > EPS ) return 1;
return 0;
}

inline void Graham(){
int i,u = 0;
for(i = 1; i < n; i++){
if(fsm(points[i].y , points[u].y)||feq(points[i].y , points[u].y)
&&fsm(points[i].x , points[u].x) )u = i;
}
swap(points[0],points[u]);
p0 = points[0];
sort( points+1, points + n, cmp );
graham[0] = 0;
graham[1] = 1;
graham[2] = 2;
top = 2;
for( i = 3; i < n; i++){
while(difcross(points[i],points[graham[top]],points[graham[top-1]])                   > EPS){
top--;
if(top == 0)break;
}
graham[++top] = i;
}
}

double ans,R;
inline void solve(){
Graham();
ans = 0;
for(int i = 0; i < top; ++i){
ans += pdis(points[graham[i]],points[graham[i+1]]);
}
ans += pdis(points[graham[0]],points[graham[top]]);
ans += 2.0*PI*R;
printf("%.0lf\n",ans);
}

int main(){
scanf("%d%lf",&n,&R);
for(int i = 0; i < n; ++i)
points[i].input();
solve();
}

/*POJ 2007 Scrambled Polygon */
//求凸包的过程中极角排序这个思想的应用,非常重要,注意sort中的cmp怎么写的
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))
#define EPS 1e-8
#define PI acos(-1.0)
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b

const int MAXN = 55;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};

inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
Point p0;
int n;
Point points[MAXN];
inline int cmp(Point a, Point b)
{
double k = difcross(p0, a, b);
if(feq(k,0) && fbg(pdis(a, p0) , pdis(b, p0)))return 1;
else if( k > EPS ) return 1;
return 0;
}

int main(){
int top = 0;
double x0,y0;
while(scanf("%lf%lf",&x0,&y0) != EOF){
//if(x0 == -1 && y0 == -1)break;
points[top++] = Point(x0,y0);
}
p0 = points[0];
sort(points+1,points+1+top,cmp);
for(int i = 0; i < top; ++i)
printf("(%.0lf,%.0lf)\n",points[i].x,points[i].y);
return 0;
}

/*POJ 1873 The Fortified Forest*/
//1999年worldfinal的题,纯暴力可以过,用位运算的枚举,枚举出2^n种状态,取最优解法即可。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define EPS 1e-6
#define max(a,b) ((a)>(b) ? (a) : (b))
#define min(a,b) ((a)<(b) ? (a) : (b))
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
const int MAXN = 20;
double len[MAXN];
double val[MAXN];
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}

inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int graham[MAXN],top;
Point p0;
Point p[MAXN],points[MAXN];
inline int cmp(Point a, Point b)
{
double k = difcross(p0, a, b);
if(feq(k,0) && fbg(pdis(a, p0) , pdis(b, p0)))return 1;
else if( k > EPS ) return 1;
return 0;
}

inline void Graham(Point points[],int n){
if(n < 3){
if(n == 0 || n == 1)top = 0;
if(n == 2)top = 1;
return;
}
int i,u = 0;
for(i = 1; i < n; i++){
if(fsm(points[i].y , points[u].y)||feq(points[i].y , points[u].y)
&&fsm(points[i].x , points[u].x) )u = i;
}
swap(points[0],points[u]);
p0 = points[0];
sort( points+1, points + n, cmp );
graham[0] = 0;
graham[1] = 1;
graham[2] = 2;
top = 2;
for( i = 3; i < n; i++){
while(difcross(points[i],points[graham[top]],points[graham[top-1]])> EPS){
top--;
if(top == 0)break;
}
graham[++top] = i;
}
}
inline double girth(){
double ans = 0;
for(int i = 0; i < top ; ++i){
ans += pdis(points[graham[i]],points[graham[i+1]]);
}
ans += pdis(points[graham[top]],points[graham[0]]);
return ans;
}

int main(){
int n;
int cas = 0;
while(scanf("%d",&n) != EOF){
if(n == 0)break;
cas ++;
if(cas != 1)puts("");
for(int i = 0; i < n; ++i){
p[i].input();
scanf("%lf",&val[i]);
scanf("%lf",&len[i]);
}
int tn = 1<<n;
double ans = 1e100,tans;
int res = 0;
for(int tag = 0; tag < tn; tag ++){
int tt = 0;double tlen = 0,tval = 0;
for(int j = 0; j < n; ++j){
int t = 1<<j;
if(t&tag)
points[tt++] = p[j];
else {
tlen += len[j];
tval += val[j];
}
}
Graham(points,tt);
double need_len = girth();
if(fbgeq(tlen,need_len) && fbg(ans,tval)){
ans = tval;
res = tag;
tans = tlen - need_len;
}

}
printf("Forest %d\n",cas);
printf("Cut these trees:");
for(int j = 0; j < n; ++j){
if((1<<j)&res)continue;
printf(" %d",j+1);
}
puts("");
printf("Extra wood: %.2lf\n",tans);
}
return 0;
}

/*POJ 1228 Grandpa's Estate*/
//题意比较难理解,给n个凸多边形上的点,问能不能唯一确定这个凸多边形。
//刚写凸包的时候写的这个题,代码风格和现在很不一样
/*
这是这题的做法,黑书上的题
1. n<=5,一律输出NO
2. 所有点共线,NO
3. 凸包上每条边上至少有三点,否则NO
*/

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define eps 1e-8
#define MAXN 1005
#define zero(x) (((x)>0?(x):-(x))<eps)

struct point
{
double x,y;
};

point P[MAXN],convex[MAXN];
int t,n,i,j,flag[MAXN],k;
double xmult(point p1,point p2,point p0){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
point p1,p2;
int graham_cp(const void* a,const void* b){
double ret=xmult(*((point*)a),*((point*)b),p1);
return zero(ret)?(xmult(*((point*)a),*((point*)b),p2)>0?1:-1):(ret>0?1:-1);
}
void _graham(int n,point* p,int& s,point* ch){
int i,k=0;
for (p1=p2=p[0],i=1;i<n;p2.x+=p[i].x,p2.y+=p[i].y,i++)
if (p1.y-p[i].y>eps||(zero(p1.y-p[i].y)&&p1.x>p[i].x))
p1=p[k=i];
p2.x/=n,p2.y/=n;
p[k]=p[0],p[0]=p1;
qsort(p+1,n-1,sizeof(point),graham_cp);
for (ch[0]=p[0],ch[1]=p[1],ch[2]=p[2],s=i=3;i<n;ch[s++]=p[i++])
for (;s>2&&xmult(ch[s-2],p[i],ch[s-1])<-eps;s--);
}

int graham(int n,point* p,point* convex,int maxsize=0,int dir=1){
point* temp=new point
;
int s,i;
_graham(n,p,s,temp);
for (convex[0]=temp[0],n=1,i=(dir?1:(s-1));dir?(i<s):i;i+=(dir?1:-1))
if (maxsize||!zero(xmult(temp[i-1],temp[i],temp[(i+1)%s])))
convex[n++]=temp[i];
delete []temp;
return n;
}

int dot_online_in(point p,point l1,point l2)
{
return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps;
}

int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%lf %lf",&P[i].x,&P[i].y);
}
if(n<=5)
{
printf("NO\n");
continue;
}
k=0;
for(i=1;i<n-1;i++)
{
if(xmult(P[0],P[n-1],P[i])!=0)
{
k=1;
break;
}
}
if(!k)
{
printf("NO\n");
continue;
}
int M=graham(n,P,convex,0,1);
if(M==n)
{
printf("NO\n");
continue;
}
memset(flag,0,sizeof(flag));
for(i=0;i<n;i++)
{
for(j=0;j<M-1;j++)
{
if(dot_online_in(P[i],convex[j],convex[j+1]))
{
flag[j]++;
}
}
if(dot_online_in(P[i],convex[M-1],convex[0]))
{
flag[M-1]++;
}
}
k=0;
for(i=0;i<M;i++){
if(flag[i]<3){
k=1;
break;
}
}
if(!k)
printf("YES\n");

else printf("NO\n");

}
return 0;
}
/*POJ 3348 Cows */
//求凸包面积

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
using namespace std;

const int maxn = 10010;
struct Point {
double x;
double y;
};
Point p[maxn];
int n;

double pdis(Point a,Point b){
return sqrt((a.x - b.x)*(a.x - b.x)+(a.y - b.y)*(a.y - b.y));
}
double det(Point p0,Point p1,Point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y - p0.y);
}
int cmp(Point a,Point b){
double k = det(p[0],a,b);
if(k > 0)return 1;
else if(k == 0 && pdis(p[0],a) - pdis(p[0],b) > 0)return 1;
return 0;
}
int graham[maxn];
int top;
void Graham(){
int i,u = 0;
for(i = 1; i < n; i++){
if(p[i].y < p[u].y || (p[i].y == p[u].y && p[i].x < p[u].x))u = i;
}
Point t;
t.x = p[u].x;t.y = p[u].y;
p[u] = p[0];
p[0] = t;
sort(p+1,p+n,cmp);
graham[0] = 0;
graham[1] = 1;
graham[2] = 2;
top = 2;
for(i = 3; i < n; i++){
while(det(p[i],p[graham[top]],p[graham[top-1]]) > 0){
top--;
if(top == 0)break;
}
graham[++top] = i;
}
}

int main(){
scanf("%d",&n);
for(int i = 0; i < n; i++){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
double area = 0;
Graham();
Point t;
t.x = 0.000;t.y = 0.000;
for(int i = 0; i < top; i++){
area += det(t,p[graham[i]],p[graham[i+1]]);
}
area += det(t,p[graham[top]],p[graham[0]]);
area = fabs(area)/2;
area /= 50;
int ans = int(area);
printf("%d\n",ans);
return 0;
}

三、面积问题,公式问题
/*POJ 1654 Area */
//多边形面积计算,利用叉积,水题

#include <cstdio>
#include <cstring>
using namespace std;

struct p{
int x,y;
};

int square(p a,p b,p c){
int r = (b.x-a.x)*(c.y-b.y)-(b.y-a.y)*(c.x-b.x);
return r;
}
int main()
{

int n;
int move[10][2]={{0,0},{-1,-1},{0,-1},{1,-1},{-1,0},{0,0},{1,0},{-1,1},{0,1},{1,1}
};
scanf("%d",&n);
char ch[1000100];
while(n--)
{
scanf("%s",ch);
int len = strlen(ch);
int i,j,k;
p a,b,c;
a.x=0,a.y=0;
c.x=a.x+move[ch[0]-'0'][0];
c.y=a.y+move[ch[0]-'0'][1];

__int64 s =0;
for(i=1;i<len;i++)
{
b=c;
c.x=b.x+move[ch[i]-'0'][0];
c.y=b.y+move[ch[i]-'0'][1];
s+=square(a,b,c);
}
if(s<0)s=-s;
printf("%I64d",s/2);
if(s%2)
printf(".5");
printf("\n");

}
return 0;
}

/*POJ 1265 Area */
/*利用Pick定理,Pick定理是说,假设平面上有一个顶点全在格点上的多边形P,那么其面积S(P)应该等于i+b/2-1,其中i为多边形内部所含的格点数,b是多边形边界上的格点数。关于pick定理的证明,这里有一个http://www.matrix67.com/blog/archives/768*/
//求边上有多少个格点的时候用最大公约数
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;

struct point{double x,y;};

int gcd(int a,int b){
if(b == 0)return a;
else return gcd(b,a%b);
}
double area_polygon(int n,point* p){
double s1=0,s2=0;
int i;
for (i=0;i<n;i++)
s1+=p[(i+1)%n].y*p[i].x,s2+=p[(i+1)%n].y*p[(i+2)%n].x;
return fabs(s1-s2)/2;
}
point p[103];
int main()
{
int testcase;
int n;
int i,j;
double I,E,s;
int x,y;

scanf("%d",&testcase);
for(i=1;i<=testcase;i++)
{
E=0;

scanf("%d",&n);
point temp;
temp.x=temp.y=0;
p[0]=temp;
double dx,dy;
for(j=1;j<=n;j++)
{

scanf("%lf%lf",&dx,&dy);
temp.x+=dx;
temp.y+=dy;
p[j]=temp;
}
s=area_polygon(n,p);
for(j=1;j<n;j++)
E+=gcd((int)(abs(p[j].x-p[j-1].x)+0.1),(int)(abs(p[j].y-p[j-1].y)+0.1));
E+=gcd((int)(abs(p[n-1].x-p[0].x)+0.1),(int)(abs(p[n-1].y-p[0].y)+0.1));

I=s+1-E/2;
printf("Scenario #%d:\n",i);
printf("%.0lf %.0lf %.1lf\n\n",I,E,s);
}
return 0;
}

/*POJ 2954 Triangle*/
//Pick定理的应用
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

struct Point{
double x,y;
void input(){
scanf("%lf%lf",&x,&y);
}
};
Point a,b,c;
inline int Input(){
a.input();
b.input();
c.input();
if(a.x == 0 && b.x == 0 && c.x == 0
&& a.y == 0 && b.y == 0 && c.y == 0)return 0;
return 1;
}
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}

inline double trarea(Point a,Point b,Point c){
return   fabs(difcross(a,b,c))/2.0;
}
inline int gcd(int a,int b){
if(b == 0)return a;
else return gcd(b,a%b);
}
int main(){
while(Input()){
double area = trarea(a,b,c);
double E = 0;
E += gcd((int)fabs(a.x-b.x),(int)fabs(a.y-b.y));
E += gcd((int)fabs(b.x-c.x),(int)fabs(b.y-c.y));
E += gcd((int)fabs(c.x-a.x),(int)fabs(c.y-a.y));

double ans = area+1-E/2;
printf("%.0lf\n",ans);
}
return 0;
}

四、半平面交
关于半平面交,见下下一篇文章《半平面交》文章里关于半平面交的所有的题目都有

五、计算几何背景,实际上解题的关键是其他问题(数据结构、组合数学,或者是 枚举思想)
若干道经典的离散化+扫描线的题目,ACM选手必做题目

这一部分比较难,涉及到各种数据结构,各种思想,主要不在计算几何,先空着。
/*POJ 2002 Squares*/
//给若干个点,问能组成多少个正方形,hash可以解决
#include <cstdio>
#include <cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
struct seg{
int x,y;
};
seg points[2010];

vector < seg  > hash[40010];
int find(int x1,int y1){
int t = abs((x1+y1)/2);
int flag = 0;
for(int i = 0; i < hash[t].size(); i++){
seg tq = hash[t][i];
if(tq.x == x1 && tq.y == y1){
flag = 1;
break;
}
}
return flag;
}

int main(){
int n,i,j;
while(scanf("%d",&n)!=EOF){
if(n == 0)break;
int cnt = 0;
int x,y;
for(i = 0; i <= 40000; i++)hash[i].clear();
for(i = 0; i < n; i++){
scanf("%d%d",&x,&y);
points[i].x = x;points[i].y = y;
int mid = abs((x+y)/2);
if(!find(x,y))hash[mid].push_back(points[i]);
}
int a1,b1,a2,b2,x1,y1,x2,y2;
for(i = 0; i < n; i++){
for(j = i+1; j < n; j++){
a1 = points[i].x;
a2 = points[i].y;
b1 = points[j].x;
b2 = points[j].y;
x1 = a1 + b2 - a2;
y1 = a2 - b1 + a1;
x2 = b1 + b2 - a2;
y2 = b2 - b1 + a1;
if(find(x1,y1) && find(x2,y2))cnt++;
x1 = a1 - b2 + a2;
y1 = a2 + b1 - a1;
x2 = b1 - b2 + a2;
y2 = b2 + b1 - a1;
if(find(x1,y1) && find(x2,y2))cnt++;
}
}
printf("%d\n",cnt/4);
}
return 0;
}

六、随机算法
/*POJ 2420 A Star not a Tree?*/
/*第一次做关于随机算法的题目,求多边形的费马点,所谓费马点,就是多边形中的一个点,该点到其他点的距离之和最短,好像只有三角形可以有公式去求费马点,而四边形以上的多边形就要用其他方法了,这个方法就是随机化变步长贪心法、就是选取初始点,然后上下左右向四个方向移动这个点,一直选取最优解,直到上下左右四个方向都不如该点时就OK,然后改变步长继续判断*/
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

const int MAXN = 1000;

struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};

Point points[MAXN],tmp;
int n;
double di[4][2] = {{0,1.0},{0,-1.0},{1.0,0},{-1.0,0}};
inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

inline double cal(Point a){
double res = 0;
for(int i = 0; i < n; ++i){
res += pdis(points[i],a);
}
return res;
}

int main(){
while(scanf("%d",&n) != EOF){
for(int i = 0; i < n; ++i)points[i].input();
Point tt;
tmp = points[0];
double ans = cal(tmp);
double step = 1000;
bool flag = 1;
while(step > 0.2){
flag = 1;
while(flag){
flag = 0;
for(int i = 0; i < 4; ++i){
tt = Point(tmp.x+di[i][0]*step,tmp.y+di[i][1]*step);
double caltt = cal(tt);
if(caltt < ans){
ans = caltt;
tmp = tt;
flag = 1;
}
}
}
step /= 2;
}
printf("%.0lf\n",ans);
}
return 0;
}

七、解析几何

/*POJ 1375 Intervals */
//求圆的切线的一道题,求圆的切点的时候用向量旋转即可
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define EPS 1e-8
#define max(a,b) ((a)>(b) ? (a) : (b))
#define min(a,b) ((a)<(b) ? (a) : (b))
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
const int MAXN = 1000;

struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
void output(){
printf("%lf %lf\n",x,y);
}
};
struct Node{
double lx,rx;
};
Point light;
inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline Point rotate(Point p,double angle){
Point res;
res.x=p.x*cos(angle)-p.y*sin(angle);
res.y=p.x*sin(angle)+p.y*cos(angle);
return res;
}

inline void GetcutPoint(Point o,double r,Point &res1,Point &res2){
Point t = Point(light.x-o.x,light.y-o.y);
double tmp = r/pdis(o,light);
double angle = acos(tmp);
t.x /= pdis(o,light);
t.y /= pdis(o,light);
t.x *= r;
t.y *= r;
res1 = rotate(t,angle);
res2 = rotate(t,-angle);
res1.x += o.x;res1.y += o.y;
res2.x += o.x;
res2.y += o.y;
}
inline void getline(Point x,Point y,double &a,double &b,double &c){
a = y.y - x.y;
b = x.x - y.x;
c = y.x * x.y - x.x * y.y;
}

inline int cmp(Node a,Node b){
return a.lx < b.lx;
}
int main(){
int n;
while(scanf("%d",&n) != EOF){
if(n == 0)break;
light.input();
double r;
Point o;
Node nodes[MAXN];
for(int i = 0; i < n; ++i){
o.input();
scanf("%lf",&r);
Point res1,res2;
GetcutPoint(o,r,res1,res2);
//res1.output();
//res2.output();
double a,b,c,x1,x2;
getline(light,res1,a,b,c);
x1 = (-c)/a;
getline(light,res2,a,b,c);
x2 = (-c)/a;
nodes[i].lx = min(x1,x2);
nodes[i].rx = max(x1,x2);
}
sort(nodes,nodes+n,cmp);
double leftx = nodes[0].lx;
double rightx = nodes[0].rx;

printf("%.2lf",nodes[0].lx);
double prevy=nodes[0].rx;
for(int i=1;i<n;i++) {
if(nodes[i].lx>prevy) {
printf(" %.2lf\n%.2lf",prevy,nodes[i].lx);
}
if(prevy<nodes[i].rx) prevy=nodes[i].rx;
}
printf(" %.2lf\n",prevy);
putchar('\n');

}
return 0;
}

/*poj 1329*/
//求三角形的外接圆,裸的三角形外接圆,比较水,只要控制输出就行了
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define sqr(a) ( (a*a) )
#define EPS 1e-6
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
bool input(){
if(scanf("%lf%lf",&x,&y)!= EOF)return 1;
return 0;
}
};
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}

inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline double trarea(Point a,Point b,Point c){
return   fabs(difcross(a,b,c))/2.0;
}
inline Point get_out_circle(Point a,Point b,Point c){
double c1,c2,xa,xb,xc,ya,yb,yc;
Point o;
xa = a.x,xb = b.x,xc = c.x;
ya = a.y,yb = b.y,yc = c.y;
c1 = (sqr(xa)+sqr(ya)-sqr(xb)-sqr(yb))/2.0;
c2 = (sqr(xa)+sqr(ya)-sqr(xc)-sqr(yc))/2.0;
o.x = (c1*(ya-yc)-c2*(ya-yb))/((xa-xb)*(ya-yc)-(xa-xc)*(ya-yb));
o.y = (c1*(xa-xc)-c2*(xa-xb))/((ya-yb)*(xa-xc)-(ya-yc)*(xa-xb));
return o;
}

inline double get_out_r(Point a,Point b,Point c){
double ab = pdis(a,b),bc = pdis(b,c),ca = pdis(c,a),s = trarea(a,b,c);
return ab*bc*ca/(4*s);
}
int main(){
Point a,b,c;
while(a.input()){

b.input();
c.input();
Point o = get_out_circle(a,b,c);
double r = get_out_r(a,b,c);
bool flagx,flagy;
if(o.x > EPS)flagx = 1;
else flagx = 0;
if(o.y > EPS)flagy = 1;
else flagy = 0;
printf("(x ");
if(flagx)printf("- %.3lf)^2 + ",o.x);
else printf("+ %.3lf)^2 + ",-o.x);
printf("(y ");
if(flagy)printf("- %.3lf)^2 ",o.y);
else printf("+ %.3lf)^2 ",-o.y);
printf("= %.3lf^2\n",r);

printf("x^2 + y^2 ");
if(flagx)printf("- %.3lfx ",2*o.x);
else printf("+ %.3lfx ",-2*o.x);
if(flagy)printf("- %.3lfy ",2*o.y);
else printf("+ %.3lfy ",-2*o.y);
double tmp = o.x*o.x+o.y*o.y-r*r;
if(tmp > 0)printf("+ %.3lf = 0\n",tmp);
else printf("- %.3lf = 0\n",-tmp);
puts("");
}
return 0;
}

/*POJ 2354 Titanic*/
//求球面上两个点的距离,给的是地理经纬坐标,以前没遇到过这种关于球的问题
//由于这个题的输入输出比较烦,所以就换了两个同样的问题,输入输出比较简单一点的,和此题一样

/*
*假设地球是球体,
*设地球上某点的经度为lambda,纬度为phi,
*则这点的空间坐标是
*x=cos(phi)*cos(lambda)
*y=cos(phi)*sin(lambda)
*z=sin(phi)
*设地球上两点的空间坐标分别为(x1,y1,z1),(x2,y2,z2)
*直线距离即为R*sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1)),
*则它们的夹角为 A = acos(x1 * x2 + y1 * y2 + z1 * z2)
*球面距离为 A*R/2(R 即地球半径)
*/
/*poj 2587*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M =1005;
const double P=acos(-1.0);
struct air
{
double lon,lat,j,w;
double x,y,z;
}a[M];
int n,ans;
double minn,maxn;
double dist(air a1,air a2)
{
return (a1.x-a2.x)*(a1.x-a2.x)+(a1.y-a2.y)*(a1.y-a2.y)+(a1.z-a2.z)*(a1.z-a2.z);
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&a[i].lat,&a[i].lon);
a[i].j=a[i].lon;
a[i].w=a[i].lat;
a[i].lat*=P/180;
a[i].lon*=P/180;
a[i].x=cos(a[i].lat)*cos(a[i].lon);
a[i].y=cos(a[i].lat)*sin(a[i].lon);
a[i].z=sin(a[i].lat);
}
minn=999999.0;
for(int i=0;i<n;i++)
{
maxn=0;
for(int j=0;j<n;j++)
{
double temp=dist(a[i],a[j]);
if(temp>maxn)maxn=temp;
}
if(minn>maxn)
{
minn=maxn;
ans=i;
}
}
printf("%.2lf %.2lf\n",a[ans].w,a[ans].j);
return 0;
}

/*poj 3407*/

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const double P=acos(-1.0);
struct node
{
double x, y, z;
double lat,lon;
};
int main()
{
double lat1, latm1, lon1, lonm1;
double lat2, latm2, lon2, lonm2;
node p1, p2;
char dir1, dir2;
while(scanf("%lf %lf %c %lf %lf %c",&lat1,&latm1,&dir1,&lon1,&lonm1,&dir2)!=EOF){
p1.lat=(lat1+latm1/60)* P/180;
p1.lon=(lon1 +lonm1/60)*P/180;
if(dir1=='S')p1.lat*=-1.0;
if(dir2=='W')p1.lon*=-1.0;
p1.x=cos(p1.lat)*cos(p1.lon);
p1.y=cos(p1.lat)*sin(p1.lon);
p1.z=sin(p1.lat);
scanf("%lf %lf %c %lf %lf %c",&lat2,&latm2,&dir1,&lon2,&lonm2,&dir2);
p2.lat=(lat2+latm2/60)*P/180;
p2.lon=(lon2+lonm2/60)*P/180;
if(dir1=='S')p2.lat*=-1.0;
if(dir2=='W')p2.lon*=-1.0;
p2.x=cos(p2.lat)*cos(p2.lon);
p2.y=cos(p2.lat)*sin(p2.lon);
p2.z=sin(p2.lat);
double angle=acos(p1.x*p2.x+p1.y*p2.y+p1.z*p2.z);
printf("%.3lf\n",angle*6370.0);
}

return 0;
}

/*POJ 1106 Transmitters*/
//这题什么也不用,直接枚举就行了,只用了一个叉积
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define EPS 1e-16
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
const int MAXN = 155;
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
bool input(){
if(scanf("%lf%lf",&x,&y)!=EOF)return 1;
return 0;
}
};
inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
Point points[MAXN];
Point o;
double r;
int main(){
while(o.input()){
scanf("%lf",&r);
if(fsm(r,0))break;
int n;
scanf("%d",&n);
int top = 0;
Point tmp;
while(n --){
tmp.input();
if(fbg(pdis(tmp,o),r))continue;
points[top++] = tmp;
}
int ans = 0,cnt;
for(int i = 0; i < top; ++i){
Point tt = Point(2*o.x-points[i].x,2*o.y-points[i].y);
cnt = 0;
for(int j = 0; j < top; ++j)
if(fsmeq(difcross(points[i],tt,points[j]),0))cnt++;
if(ans < cnt)ans = cnt;
}
printf("%d\n",ans);
}
return 0;
}

/*http://www.codeforces.com/contest/32/problem/E*/
//补充一个线段求交的题,要考虑各种情况,特别是共线的时候对两种不同的线段采取不同的策略。
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define EPS 1e-8
#define max(a,b) ((a)>(b) ? (a) : (b))
#define min(a,b) ((a)<(b) ? (a) : (b))
#define feq(a,b) (fabs((a)-(b))<EPS)//a==b
#define fbg(a,b) ((a) > EPS+(b)) //a > b
#define fsm(a,b) ((b) > EPS+(a)) //a < b
#define fbgeq(a,b) ((a) >= (b)-EPS)  //a >= b
#define fsmeq(a,b) ((b) >= (a)-EPS)  //a <= b
#define sqr(a) ((a)*(a))

struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}
void input(){
scanf("%lf%lf",&x,&y);
}
};

struct Segment{
Point a,b;
Segment(){}
Segment(Point _a,Point _b):a(_a),b(_b){}
};
struct Line{
double a,b,c;
};

Point p1,p2,rp2;
Segment wall,mirr;
inline double dotcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);
}
inline double sqrpdis(Point a,Point b){
return (a.x - b.x)*(a.x - b.x)+(a.y - b.y)*(a.y - b.y);
}
inline double difcross(Point a,Point b,Point c){
return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}

inline Point Perpendicular(Point p, Segment s)
{
Point tp;
double r = dotcross( s.a,p, s.b)/sqrpdis(s.a,s.b);
tp.x=s.a.x+r*(s.b.x-s.a.x);
tp.y=s.a.y+r*(s.b.y-s.a.y);
return Point(2*tp.x-p.x,2*tp.y-p.y);
}
inline bool SegIntersect(Segment s1,Segment s2)
{

double mxs1x = max(s1.a.x,s1.b.x), mns1x = min(s1.a.x,s1.b.x);
double mxs2x = max(s2.a.x,s2.b.x), mns2x = min(s2.a.x,s2.b.x);
double mxs1y = max(s1.a.y,s1.b.y), mns1y = min(s1.a.y,s1.b.y);
double mxs2y = max(s2.a.y,s2.b.y), mns2y = min(s2.a.y,s2.b.y);
return fsmeq(difcross(s1.a,s1.b,s2.a)*difcross(s1.a,s1.b,s2.b), 0)&&
fsmeq(difcross(s2.a,s2.b,s1.a)*difcross(s2.a,s2.b,s1.b), 0)&&
fbgeq(mxs1x, mns2x)&&fbgeq(mxs2x, mns1x) &&
fbgeq(mxs1y, mns2y)&&fbgeq(mxs2y, mns1y);
}
inline bool check(){
Segment s = Segment(p1,p2);

if(!SegIntersect(s,wall)){
if(!SegIntersect(s,mirr)||
(feq(difcross(mirr.a,p1,p2),0)&&feq(difcross(mirr.b,p1,p2),0)))
return 1;
}
return 0;
}
inline void getline(Point x,Point y,Line &l){
l.a = y.y - x.y;
l.b = x.x - y.x;
l.c = y.x * x.y - x.x * y.y;
}
bool line_intersect(Line l1,Line l2,Point &p)
{
double d=l1.a*l2.b-l2.a*l1.b;
if (feq(d, 0)) return 0;
p.x = (l2.c*l1.b-l1.c*l2.b)/d;
p.y = (l2.a*l1.c-l1.a*l2.c)/d;
return true;
}

inline bool check2(){
if( fsm(difcross(mirr.a, mirr.b, p1)*difcross(mirr.a, mirr.b, p2), 0) )return 0;
Point p3;Line l1,l2;
getline(mirr.a,mirr.b,l2);
double a1 = l2.a,b1 = l2.b,c1 = l2.c;
p3.x = ((sqr(b1) - sqr(a1)) * p2.x - 2 * a1 * b1 * p2.y - 2 * a1 * c1) / (sqr(a1) + sqr(b1));
p3.y = ((sqr(a1) - sqr(b1)) * p2.y - 2 * a1 * b1 * p2.x - 2 * b1 * c1) / (sqr(a1) + sqr(b1));

rp2 = p3;
Segment s = Segment(p1,rp2);
Segment s1 = Segment(p2,rp2);

Point tt;
getline(p1,rp2,l1);
line_intersect(l1,l2,tt);
if (! (tt.x >= min(mirr.a.x, mirr.b.x) &&
tt.x <= max(mirr.a.x, mirr.b.x) &&
tt.y >= min(mirr.a.y, mirr.b.y) && tt.y <= max(mirr.a.y, mirr.b.y)))
return 0;

s1 = Segment(p2,tt);
if(SegIntersect(s1,wall))return 0;
s1 = Segment(p1,tt);
if(SegIntersect(s1,wall))return 0;
return 1;
}
int main(){
p1.input();
p2.input();
wall.a.input();
wall.b.input();
mirr.a.input();
mirr.b.input();
if(check()){
printf("YES\n");
return 0;
}
if(check2())
printf("YES\n");
else printf("NO\n");
}

/*POJ 1673 EXOCENTER OF A TRIANGLE*/
//求三角形垂心,输出时要加eps,不然wa
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define EPS 1e-8
struct Point{
double x,y;
Point(){}
Point(double _x,double _y):x(_x),y(_y){}

void input(){
scanf("%lf%lf",&x,&y);
}
};
struct Line{
double a,b,c;
Line(){}

Line(double _a,double _b,double _c):a(_a),b(_b),c(_c){}
};

inline bool line_intersect(Line l1,Line l2,Point &p)
{
double d=l1.a*l2.b-l2.a*l1.b;
if (fabs(d) <= EPS) return 0;
p.x = (l2.c*l1.b-l1.c*l2.b)/d;
p.y = (l2.a*l1.c-l1.a*l2.c)/d;
return true;
}

inline double difcross(Point p0,Point p1,Point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
inline double pdis(Point a,Point b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline void getline(Point a,Point b,Point c,Line &l){
l.a = c.x - b.x;
l.b = c.y - b.y;
l.c = (b.y-c.y)*a.y-(c.x-b.x)*a.x;
if(l.a < -EPS){
l.a = -l.a;
l.b = -l.b;
l.c = -l.c;
}
}

inline double trarea(Point a,Point b,Point c){
return   fabs(difcross(a,b,c))/2.0;
}
inline Point GetChuiXin(Point a,Point b,Point c)
{
Line l1,l2;
getline(a,b,c,l1);
getline(c,a,b,l2);
Point ans;
line_intersect(l1,l2,ans);
return ans;

}

int main(){
Point a,b,c,o;
int cas;
scanf("%d",&cas);
while(cas --){
a.input();
b.input();
c.input();
o = GetChuiXin(a,b,c);
printf("%.4lf %.4lf\n",o.x+EPS,o.y+EPS);
}
return 0;
}

八、旋转卡壳
要理解旋转卡壳到底是个什么东西,最经典的问题就是求凸包的最近距离
/*POJ 2187 Beauty Contest*/
//该题数据比较水,直接求凸包然后枚举也能过,但有些题就必须用卡壳了,比如说:
//http://acm.tju.edu.cn/toj/showp2847.html这一题考的就是卡壳,不用卡壳是一定超时的。

///由于这个东西相对比较难,单独拉到下一篇文章(下一篇文章,旋转卡壳卡卡~)里
九。其他问题
/*POJ 1981 Circle and Points*/
//问单位圆最多覆盖几个点。枚举,取任意两点求出圆心,然后查询圆内有多少个点,取最大值即可
#include<cmath>
#include<cstdio>
#include<cstring>
using namespace std;
#define eps 1e-6
struct node
{
double x,y;
}p[305],center;
int n,ans,maxn;
inline double dist(node a,node b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
inline void cer(node p1,node p2)
{
node p3,mid;
double r1,r2,angle;
p3.x=p1.x-p2.x;
p3.y=p1.y-p2.y;
mid.x=(p1.x+p2.x)/2;
mid.y=(p1.y+p2.y)/2;
r1=dist(p1,mid);
r2=sqrt(1-r1);
angle=atan(-p3.x/p3.y);
center.x=mid.x+r2*cos(angle);
center.y=mid.y+r2*sin(angle);
}
int main()
{
while(scanf("%d",&n),n)
{
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
maxn=1;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
if(dist(p[i],p[j])>4)continue;
ans=0;
cer(p[i],p[j]);
for(int k=0;k<n;k++)
{
double temp=dist(p[k],center);
if(temp<=1+eps)ans++;
}
if(ans>maxn)maxn=ans;
}
printf("%d\n",maxn);
}
return 0;
}

至此,计算几何题目推荐的第一部分完结,赞美神,赞美主
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: