Kuangbin 带你飞-基础计算几何专题 题解
专题基本全都是模版应用。贴一下模版
平面最近点对
const double INF = 1e16;
const int MAXN = ;
struct Point {
int x,y;
int type;
}; double dist(Point a,Point b) {
return sqrt(1.0 * (a.x - b.x) * (a.x - b.x) + 1.0 * (a.y - b.y) * (a.y - b.y));
} Point p[MAXN];
int n,s[MAXN];
int cmpx(int i,int j) {return p[i].x - p[j].x < ;}
int cmpy(int i,int j) {return p[i].y - p[j].y < ;} double closet_pair(int * s,int l,int r) {
double ans = INF;
if (r - l < ) {
for (int q = l ; q < r ; q++)
for (int w = q + ; w < r ; w++)
if ((p[s[q]].type ^ p[s[w]].type) == )
ans = min(ans,dist(p[s[q]],p[s[w]]));
return ans;
}
int lft,rht,mid = (l + r) / ;
ans = min(closet_pair(s,l,mid),closet_pair(s,mid,r));
for (lft = l ; p[s[lft]].x < p[s[mid]].x - ans; lft++);
for (rht = r - ; p[s[rht]].x > p[s[mid]].x + ans ; rht--);
sort(s + lft,s + rht,cmpy);
for (int q = lft ; q < rht ; q++) {
for (int w = q + ; w < min(rht,q + ) ; w++) {
if ((p[s[q]].type ^ p[s[w]].type) == ) {
ans = min(ans,dist(p[s[q]],p[s[w]]));
}
}
}
sort(s + lft,s + rht,cmpx);
return ans;
} int main() {
int N;
scanf("%d",&N);
for (int i = ; i < N ; i++) {
scanf("%d%d",&p[i].x,&p[i].y);
p[i].type = ;
}
for (int i = N ; i < N + N ; i++) {
scanf("%d%d",&p[i].x,&p[i].y);
p[i].type = ;
}
for (int i = ; i < N + N ; i++) s[i] = i;
sort(s,s + N + N,cmpx);
printf("%.3lf\n",closet_pair(s,, * N));
}
const double eps = 1e-;
const int INF = 0x3f3f3f3f;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
}
//叉积
double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
}
//点积
double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
//绕源点旋转B(弧度)。后X,Y变化
void transxy(double B) //
{
double tx = x;
double ty = y;
x = tx * cos(B) - ty * sin(B);
y = ty * sin(B) + tx * cos(B);
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
}
//两直线求交点。这个可以用来求线段交点。
// 首先判断线段相交然后可以直接利用这个判线段交点
//first为0表示重合,1表示平行,2表示相交
pair<int,Point> operator & (const Line &b) const
{
Point res = s;
if (sgn((s - e) ^ (b.s - b.e)) == )
{
if (sgn((s - b.e) ^ (b.s - b.e)) == )
return make_pair(,res);//重合
else return make_pair(,res);//平行
}
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));//相交
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return make_pair(,res);
}
}; double dist(Point a,Point b)
{
return sqrt((b - a) * (b - a));
}
//判断线段是否相交
bool inter(Line l1,Line l2)
{
return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= &&
sgn((l1.s - l2.s) ^ (l2.e - l1.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= ;
}
bool OnSeg(Point P,Line L)
{
return
sgn((L.s-P)^(L.e-P)) == &&
sgn((P.x - L.s.x) * (P.x - L.e.x)) <= &&
sgn((P.y - L.s.y) * (P.y - L.e.y)) <= ;
} //判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)一定注意时针顺序否则会WA
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
for(int i = ; i < n ; i++)
{
if(sgn((p[i] - a) ^ (p[(i + ) % n] - a)) < )return -;
else if(OnSeg(a,Line(p[i],p[(i + ) % n])))return ;
}
return ;
} //判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
int cnt;
Line ray,side;
cnt = ;
ray.s = p;
ray.e.y = p.y;
ray.e.x = -100000000000.0;//-INF,注意取值防止越界 for(int i = ;i < n;i++)
{
side.s = poly[i];
side.e = poly[(i+)%n]; if(OnSeg(p,side))return ; //如果平行轴则不考虑
if(sgn(side.s.y - side.e.y) == )
continue; if(OnSeg(side.s,ray))
{
if(sgn(side.s.y - side.e.y) > )cnt++;
}
else if(OnSeg(side.e,ray))
{
if(sgn(side.e.y - side.s.y) > )cnt++;
}
else if(inter(ray,side))
cnt++;
}
if(cnt % == )return ;
else return -;
}
//判断凸多边形
//允许共线边
//点可以是顺时针给出也可以是逆时针给出
//点的编号1~n-1
bool isconvex(Point poly[],int n)
{
bool s[];
memset(s,false,sizeof(s));
for(int i = ;i < n;i++)
{
s[sgn( (poly[(i + ) % n]-poly[i]) ^ (poly[(i + ) % n] - poly[i]) ) + ] = true;
if(s[] && s[])return false;
}
return true;
} //点到线段的距离
//返回点到线段最近的点
Point NearestPointToLineSeg(Point P,Line L)
{
Point result;
double t = ((P - L.s)*(L.e - L.s)) / ((L.e - L.s)*(L.e - L.s));
if(t >= && t <= )
{
result.x = L.s.x + (L.e.x - L.s.x) * t;
result.y = L.s.y + (L.e.y - L.s.y) * t;
}
else
{
if(dist(P,L.s) < dist(P,L.e))
result = L.s;
else result = L.e;
}
return result;
} //*判断点在线段上
bool OnSeg(Point P,Line L)
{
return
sgn((L.s-P)^(L.e-P)) == &&
sgn((P.x - L.s.x) * (P.x - L.e.x)) <= &&
sgn((P.y - L.s.y) * (P.y - L.e.y)) <= ;
} //*判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
for(int i = ; i < n ; i++)
{
if(sgn((p[i] - a) ^ (p[(i + ) % n] - a)) < )return -;
else if(OnSeg(a,Line(p[i],p[(i + ) % n])))return ;
}
return ;
} bool inter(Line l1,Line l2)
{
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= &&
sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= ;
} //*判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
int cnt;
Line ray,side;
cnt = ;
ray.s = p;
ray.e.y = p.y;
ray.e.x = -100000000000.0;//-INF,注意取值防止越界 for(int i = ;i < n;i++)
{
side.s = poly[i];
side.e = poly[(i+)%n]; if(OnSeg(p,side))return ; //如果平行轴则不考虑
if(sgn(side.s.y - side.e.y) == )
continue; if(OnSeg(side.s,ray))
{
if(sgn(side.s.y - side.e.y) > )cnt++;
}
else if(OnSeg(side.e,ray))
{
if(sgn(side.e.y - side.s.y) > )cnt++;
}
else if(inter(ray,side))
cnt++;
}
if(cnt % == )return ;
else return -;
} 计算有向面积
double CalcArea(Point * p,int n) {
double res = 0;
for (int i = 0 ; i < n ; i++)
res += (p[i] ^ p[(i + 1) % n]);
return fabs(res);
}
POJ 2318 TOYS
给出区域,要你算出给出的每个点在第几个区域里
利用叉积的方向性二分判断在第几个区域内
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
typedef long long type;
using namespace std;
type gcd(type a, type b) {return b == ? a : gcd(b, a % b);}
const int MAXN = ; struct Point
{
int x,y;
Point(){}
Point(int _x,int _y)
{
x = _x;y = _y;
}
Point operator - (const Point &b)const
{
return Point(x - b.x,y - b.y);
}
int operator * (const Point &b)const
{
return x*b.x + y*b.y;
}
int operator ^ (const Point &b)const
{
return x*b.y - y*b.x;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;e = _e;
}
}; int xmult(Point p0,Point p1,Point p2) //计算p0p1 X p0p2
{
return (p1 - p0) ^ (p2 - p0);
} Line line[MAXN];
int ret[MAXN];
int N,M;
double X1,Y1,X2,Y2; int main()
{
bool first = true;
while (scanf("%d",&N) != EOF)
{
if(N == ) break;
if (first) first = false;
else putchar('\n');
memset(ret,,sizeof(ret));
scanf("%d%lf%lf%lf%lf",&M,&X1,&Y1,&X2,&Y2);
int UI,LI;
for (int i = ; i < N ; i++)
{
scanf("%d%d",&UI,&LI);
line[i] = Line(Point(UI,Y1),Point(LI,Y2));
}
line[N] = Line(Point(X2,Y1),Point(X2,Y2));
Point p;
memset(ret,,sizeof(ret));
while (M--)
{
int x,y;
scanf("%d%d",&x,&y);
p = Point(x,y);
int l = ,r = N;
int ans;
while (l <= r)
{
int mid = (l + r) / ;
if (xmult(p,line[mid].s,line[mid].e) < )
{
ans = mid;
r = mid - ;
}
else l = mid + ;
}
ret[ans]++;
}
for (int i = ; i <= N ; i++) printf("%d: %d\n",i,ret[i]);
}
return ;
}
POJ 2398 Toy Storage
跟上面的那个题一样的只是改变了一下答案的方式
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
typedef long long type;
using namespace std;
type gcd(type a, type b) {return b == ? a : gcd(b, a % b);}
const int MAXN = ; struct Point
{
int x,y;
Point(){}
Point(int _x,int _y)
{
x = _x;y = _y;
}
Point operator - (const Point &b)const
{
return Point(x - b.x,y - b.y);
}
int operator * (const Point &b)const
{
return x*b.x + y*b.y;
}
int operator ^ (const Point &b)const
{
return x*b.y - y*b.x;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point _s,Point _e)
{
s = _s;e = _e;
}
}; int xmult(Point p0,Point p1,Point p2) //计算p0p1 X p0p2
{
return (p1 - p0) ^ (p2 - p0);
} Line line[MAXN];
int ret[MAXN];
int N,M;
int num[MAXN];
double X1,Y1,X2,Y2;
const int cmp(Line a,Line b)
{
return a.s.x < b.s.x;
} int main()
{
bool first = true;
while (scanf("%d",&N) != EOF)
{
if(N == ) break;
memset(ret,,sizeof(ret));
scanf("%d%lf%lf%lf%lf",&M,&X1,&Y1,&X2,&Y2);
int UI,LI;
for (int i = ; i < N ; i++)
{
scanf("%d%d",&UI,&LI);
line[i] = Line(Point(UI,Y1),Point(LI,Y2));
}
line[N] = Line(Point(X2,Y1),Point(X2,Y2));
Point p;
sort(line ,line + N + ,cmp);
memset(ret,,sizeof(ret));
while (M--)
{
int x,y;
scanf("%d%d",&x,&y);
p = Point(x,y);
int l = ,r = N;
int ans;
while (l <= r)
{
int mid = (l + r) / ;
if (xmult(p,line[mid].s,line[mid].e) < )
{
ans = mid;
r = mid - ;
}
else l = mid + ;
}
ret[ans]++;
}
for (int i = ; i <= N ; i++)num[i] = ;
for (int i = ; i <= N ; i++)
if (ret[i] > ) num[ret[i]]++;
puts("Box");
for (int i = ; i <= N ; i++)
if (num[i] > ) printf("%d: %d\n",i,num[i]);
}
return ;
}
POJ 3304 segments
如果存在这样的直线满足条件,那么可以做这条直线的垂线,那么这条垂线就会
与所有线段相交于是问题转换为询问是否存在一条直线与所有线段相交
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXN = ;
const double eps = 1e-;
/*如果有存在这样的直线,过投影相交区域作直线的垂线,
该垂线必定与每条线段相交,
问题转化为问是否存在一条线和所有线段相交
*/
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
}
}; double xmult(Point p0,Point p1,Point p2)//P0P1 ^ POP2;
{
return (p1 - p0) ^ (p2 - p0);
} bool seg_inter_line(Line l1,Line l2)//line l1,seg l2
{
return sgn(xmult(l2.s,l1.s,l1.e)) * sgn(xmult(l2.e,l1.s,l1.e)) <= ;
} double dist(Point a,Point b)
{
return sqrt((b - a) * (b - a));
} Line line[MAXN];
bool judge(Line l1,int n)
{
if (sgn(dist(l1.s,l1.e)) == ) return false;
for (int i = ; i < n ; i++)
{
if (seg_inter_line(l1,line[i]) == false) return false;
}
return true;
} int main()
{
int T,n;
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
double x1,y1,x2,y2;
for (int i = ; i < n ; i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[i] = Line(Point(x1,y1) ,Point(x2,y2));
}
bool flag = false;
for (int i = ; i < n && !flag ; i++)
for (int j = ; j < n && !flag ; j++)
{
if (judge(Line(line[i].s,line[j].s),n) ||
judge(Line(line[i].s,line[j].e),n) ||
judge(Line(line[i].e,line[j].s),n) ||
judge(Line(line[i].e,line[j].e),n))
flag = true;
}
if (flag) puts("Yes!");
else puts("No!");
}
return false;
}
POJ 1269 Intersecting Lines
直接判断直线相交的情况
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-; int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point (double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
} pair<Point,int> operator & (const Line b) const
{
Point res = s;
if (sgn((s - e) ^ (b.s - b.e)) == )
{
if (sgn((b.s - s) ^ (b.e - s)) == )
return make_pair(res,);//same
else return make_pair(res,);//parell
}
double tmp = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * tmp;
res.y += (e.y - s.y) * tmp;
return make_pair(res,);
}
}; int main()
{
int T;
scanf("%d",&T);
printf("INTERSECTING LINES OUTPUT\n");
while (T--)
{
double x1,y1,x2,y2,x3,y3,x4,y4;
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
Line line1 = Line(Point(x1,y1),Point(x2,y2));
Line line2 = Line(Point(x3,y3),Point(x4,y4));
pair<Point,int> ans = line1 & line2;
if (ans.second == ) printf("POINT %.2f %.2f\n",ans.first.x,ans.first.y);
else if (ans.second == ) puts("NONE");
else puts("LINE");
}
puts("END OF OUTPUT");
return ;
}
POJ 1556 the doors
注意如果线段相交交点是端点的话扔钱可以继续传递
所以题目总有一段特判
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point b) const
{
return x * b.x + y * b.y;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
}
}; bool inter(Line l1,Line l2)
{
return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= &&
sgn((l1.s - l2.s) ^ (l2.e - l2.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= ;
} double dist(Point a,Point b)
{
return sqrt((b - a) * (b - a));
} const int MAXN = ;
Line line[MAXN];
double dis[MAXN][MAXN];
const double INF = 1e15;
Point point[MAXN * ];
int cas,tot; bool judge(Line cur)
{
for (int i = ; i <= cas ; i++)
if (line[i].s.x == cur.s.x || line[i].s.x == cur.e.x) continue;
else if (inter(cur,line[i])) return false;
return true;
} int main()
{
// freopen("sample.txt","r",stdin);
int N;
while (scanf("%d",&N) != EOF)
{
if (N == -) break;
double x,y1,y2,y3,y4;
cas = ;
tot = ;
for (int i = ; i <= N ; i++)
{
scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4);
line[++cas] = Line(Point(x,),Point(x,y1));
line[++cas] = Line(Point(x,y2),Point(x,y3));
line[++cas] = Line(Point(x,y4),Point(x,));
point[++tot] = Point(x,y1);
point[++tot] = Point(x,y2);
point[++tot] = Point(x,y3);
point[++tot] = Point(x,y4);
}
for (int i = ; i < MAXN ; i++)
for (int j = ; j < MAXN ; j++)
dis[i][j] = i == j ? : INF;
for (int i = ; i <= tot ; i++)
{
Line tmp = Line(point[i],Point(,5.0));
if (judge(tmp)) dis[][i] = dist(point[i],Point(,5.0));
}
// for (int i = 1 ; i <= tot ; i++)
// printf("%.2lf %.2lf %.2lf\n",point[i].x,point[i].y,dis[0][i]);
for (int i = ; i <= tot ; i++)
{
for (int j = ; j <= tot ; j++)
{
if (i == j) continue;
Line tmp = Line(point[i],point[j]);
if (judge(tmp)) dis[i][j] = dist(point[i],point[j]);
}
}
for (int i = ; i <= tot ; i++)
{
Line tmp = Line(point[i],Point(,));
if (judge(tmp)) dis[i][tot + ] = dist(point[i],Point(,));
}
Line tmp = Line(Point(,),Point(,));
if (judge(tmp)) dis[][tot + ] = ;
for (int k = ; k <= tot + ; k++)
{
for (int i = ; i <= tot + ; i++)
for (int j = ; j <= tot + ; j++)
dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
}
printf("%.2f\n",dis[][tot + ]);
}
return ;
}
POJ 2653 Pick up Sticks
暴力枚举判断线段相交
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
}
}; bool inter(Line l1,Line l2)
{
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= &&
sgn((l1.s - l2.s) ^ (l2.e - l2.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= ;
} const int MAXN = ;
Line line[MAXN];
bool flag[MAXN]; int main()
{
int N;
while (scanf("%d",&N) != EOF)
{
if (N == ) break;
memset(flag,false,sizeof(flag));
for (int i = ; i <= N ; i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[i] = Line(Point(x1,y1),Point(x2,y2));
}
for (int i = ; i <= N ; i++)
{
for (int j = i + ; j <= N ; j++)
{
if (inter(line[i],line[j]))
{
flag[i] = true;
break;
}
}
}
printf("Top sticks: ");
bool first = true;
for (int i = ; i <= N ; i++)
{
if (!flag[i])
{
if (first) first = false;
else printf(", ");
printf("%d",i);
}
}
puts(".");
}
return ;
}
POJ 1066 Treasure Hunt
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
const int INF = 0x3f3f3f3f;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
} void transxy(double B) //
{
double tx = x;
double ty = y;
x = tx * cos(B) - ty * sin(B);
y = ty * sin(B) + tx * cos(B);
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
} pair<int,Point> operator & (const Line &b) const
{
Point res = s;
if (sgn((s - e) ^ (b.s - b.e)) == )
{
if (sgn((s - b.e) ^ (b.s - b.e)) == )
return make_pair(,res);
else return make_pair(,res);
}
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return make_pair(,res);
}
}; double dist(Point a,Point b)
{
return sqrt((b - a) * (b - a));
} bool inter(Line l1,Line l2)
{
return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= &&
sgn((l1.s - l2.s) ^ (l2.e - l1.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= ;
} const int MAXN = ;
Line line[MAXN];
Point s;
Point p[MAXN];
int cas; int main()
{
int n;
while (scanf("%d",&n) != EOF)
{
cas = ;
double x1,y1,x2,y2;
for (int i = ; i <= n ; i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[i] = Line(Point(x1,y1),Point(x2,y2));
p[++cas] = Point(x1,y1);
p[++cas] = Point(x2,y2);
}
scanf("%lf%lf",&x1,&y1);
s = Point(x1,y1);;
int ans = INF;
for (int i = ; i <= cas; i++)
{
int cnt = ;
Line tmp = Line(s,p[i]);
for (int j = ; j <= n ; j++)
if (inter(tmp,line[j])) cnt++;
ans = min(ans,cnt);
}
Line tmp;
tmp = Line(s,Point(,));
int cnt = ;
for (int j = ; j <= n ; j++)
if (inter(tmp,line[j])) cnt++;
ans = min(ans,cnt + ); tmp = Line(s,Point(,));
cnt = ;
for (int j = ; j <= n ; j++)
if (inter(tmp,line[j])) cnt++;
ans = min(ans,cnt + ); tmp = Line(s,Point(,));
cnt = ;
for (int j = ; j <= n ; j++)
if (inter(tmp,line[j])) cnt++;
ans = min(ans,cnt + ); tmp = Line(s,Point(,));
cnt = ;
for (int j = ; j <= n ; j++)
if (inter(tmp,line[j])) cnt++;
ans = min(ans,cnt + );
printf("Number of doors = %d\n",ans);
}
return ;
}
POJ 1410 Intersection
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
} void transxy(double B)
{
double tx = x;
double ty = y;
x = tx * cos(B) - ty * sin(B);
y = tx * sin(B) + ty * cos(B);
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
} pair<int,Point> operator & (const Line &b) const
{
Point res = s;
if (sgn((s - e) ^ (b.s - b.e)) == )
{
if (sgn((s - b.e) ^ (b.s - b.e)) == )
return make_pair(,res);
else return make_pair(,res);
}
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return make_pair(,res);
}
}; bool inter(Line l1,Line l2)
{
return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.s) ^ (l1.e - l1.s)) * sgn((l2.e - l1.s) ^ (l1.e - l1.s)) <= &&
sgn((l1.s - l2.s) ^ (l2.e - l1.s)) * sgn((l1.e - l2.s) ^ (l2.e - l2.s)) <= ;
} bool OnSeg(Point P,Line L)
{
return
sgn((L.s-P)^(L.e-P)) == &&
sgn((P.x - L.s.x) * (P.x - L.e.x)) <= &&
sgn((P.y - L.s.y) * (P.y - L.e.y)) <= ;
} //判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
for(int i = ; i < n ; i++)
{
if(sgn((p[i] - a) ^ (p[(i + ) % n] - a)) < )return -;
else if(OnSeg(a,Line(p[i],p[(i + ) % n])))return ;
}
return ;
} //判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
int cnt;
Line ray,side;
cnt = ;
ray.s = p;
ray.e.y = p.y;
ray.e.x = -100000000000.0;//-INF,注意取值防止越界 for(int i = ;i < n;i++)
{
side.s = poly[i];
side.e = poly[(i+)%n]; if(OnSeg(p,side))return ; //如果平行轴则不考虑
if(sgn(side.s.y - side.e.y) == )
continue; if(OnSeg(side.s,ray))
{
if(sgn(side.s.y - side.e.y) > )cnt++;
}
else if(OnSeg(side.e,ray))
{
if(sgn(side.e.y - side.s.y) > )cnt++;
}
else if(inter(ray,side))
cnt++;
}
if(cnt % == )return ;
else return -;
} int main()
{
int T;
scanf("%d",&T);
while (T--)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
Line line = Line(Point(x1,y1),Point(x2,y2));
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
if (x1 > x2) swap(x1,x2);
if (y1 > y2) swap(y1,y2);
Point tmp[];
tmp[] = Point(x1,y1);
tmp[] = Point(x2,y1);
tmp[] = Point(x2,y2);
tmp[] = Point(x1,y2);
bool flag = false;
if (inter(line,Line(tmp[],tmp[]))) flag = true;
if (inter(line,Line(tmp[],tmp[]))) flag = true;
if (inter(line,Line(tmp[],tmp[]))) flag = true;
if (inter(line,Line(tmp[],tmp[]))) flag = true;
if (inConvexPoly(line.s,tmp,) >= && inConvexPoly(line.e,tmp,) >= ) flag = true;
printf("%s\n",flag ? "T" : "F");
}
return ;
}
****POJ 1696 Space Ant
这个题目涉及到极角排序,首先题意一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,
能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.
那么可想到的方案就是最先找到Y坐标最小的点,每次尽量选择靠下方的点走。
所以涉及到当前所在点对其他未到达点的角度问题。kuangbin神用的排序方式很好。MARK学习下
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
int idx;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
}; double dist(Point a,Point b)
{
return sqrt((b - a) * (b - a));
} const int MAXN = ;
Point p[MAXN];
int pos;
bool cmp(Point a,Point b)//对p[pos]点计较排序
{
double tmp = (a - p[pos]) ^ (b - p[pos]);
if (sgn(tmp) == )
return dist(p[pos],a) < dist(p[pos],b);
else if (sgn(tmp) < ) return false;
else return true;
} int main()
{
int T;
scanf("%d",&T);
while (T--)
{
int n;
scanf("%d",&n);
for (int i = ; i < n ; i++)
{
scanf("%d%lf%lf",&p[i].idx,&p[i].x,&p[i].y);
if (i != ) if (p[i].y < p[].y || (p[i].y == p[].y && p[i].x < p[].x))
swap(p[],p[i]);
}
pos = ;
for (int i = ; i < n ; i++)
{
sort(p + i,p + n,cmp);
pos++;
}
printf("%d",n);
for (int i = ; i < n ; i++)
printf(" %d",p[i].idx);
puts("");
}
return ;
}
****POJ 3347 Kadj Squares
这个题挺厉害,首先可以直接解出每个正方形左右端点的横坐标。然后就化为区间覆盖问题
接触横坐标其实很简单。就是化为区间覆盖他的维护方式很厉害
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const int MAXN = ;
struct node
{
int l,r;
int len;
}src[MAXN];
bool del[MAXN];
int N; int main()
{
while (scanf("%d",&N) != EOF)
{
if (N == ) break;
for (int i = ; i <= N ; i++)
{
scanf("%d",&src[i].len);
src[i].l = ;
for (int j = ; j < i ; j++)
src[i].l = max(src[i].l,src[j].r - abs(src[i].len - src[j].len));
src[i].r = src[i].l + * src[i].len;
}
//for (int i = 1 ; i <= N ; i++)printf("%d %d\n",src[i].l,src[i].r);
memset(del,false,sizeof(del));
for (int i = ; i <= N ; i++)
{
for (int j = ; j < i ; j++)
{
if (src[i].l < src[j].r && src[i].len < src[j].len)
src[i].l = src[j].r;
}
for (int j = i + ; j <= N ; j++)
{
if (src[i].r > src[j].l && src[i].len < src[j].len)
src[i].r = src[j].l;
}
}
bool first = true;
for (int i = ; i <= N ; i++)
{
if (src[i].l < src[i].r)
{
if (first) first = false;
else putchar(' ');
printf("%d",i);
}
}
puts("");
}
return ;
}
POJ 2826 An Easy Problem?!
这道题就是要仔细一点有多重情况
利用线段相交判定是否这个形状的图形被封住了一点水也装不下
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
const int INF = ;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
} pair<int,Point> operator &(const Line &b)const
{
Point res = s;
if(sgn((s - e) ^ (b.s - b.e)) == )
{
if(sgn((s - b.e) ^ (b.s - b.e)) == )
return make_pair(,res);//重合
else return make_pair(,res);//平行
}
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return make_pair(,res);
}
}; bool inter(Line l1,Line l2)
{
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= &&
sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= ;
} int main()
{
int x1,y1,x2,y2,x3,y3,x4,y4;
Line l1,l2;
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
l1 = Line(Point(x1,y1),Point(x2,y2));
l2 = Line(Point(x3,y3),Point(x4,y4));
if ((sgn(l1.s.y - l1.e.y) == ) || (sgn(l2.s.y - l2.e.y) == ))
{
puts("0.00");
continue;
}
if (sgn(l1.s.y - l1.e.y) < ) swap(l1.s,l1.e);
if (sgn(l2.s.y - l2.e.y) < ) swap(l2.s,l2.e);
if (inter(l1,l2) == false)
{
puts("0.00");
continue;
}
if (inter(Line(l1.s,Point(l1.s.x,INF)),l2) == true)
{
puts("0.00");
continue;
}
if (inter(Line(l2.s,Point(l2.s.x,INF)),l1) == true)
{
puts("0.00");
continue;
}
pair<int,Point>res;
double area;
res = l1 & l2;
Point ret = res.second;
res = l1 & Line(Point(INF,l2.s.y),l2.s);
Point ret1 = res.second;
area = fabs(((l2.s - ret) ^ (ret1 - ret)) / 2.0);
res = l2 & Line(Point(INF,l1.s.y),l1.s);
Point ret2 = res.second;
area = min(area,fabs(((l1.s - ret) ^ (ret2 - ret)) / 2.0));
printf("%.2f\n",area + eps);
}
return ;
}
POJ 1039 Pipe
直接暴力枚举2个点即可
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
const double INF = 1e14;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
} pair<int,Point> operator &(const Line &b)const
{
Point res = s;
if(sgn((s - e) ^ (b.s - b.e)) == )
{
if(sgn((s - b.e) ^ (b.s - b.e)) == )
return make_pair(,res);//重合
else return make_pair(,res);//平行
}
double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
res.x += (e.x - s.x) * t;
res.y += (e.y - s.y) * t;
return make_pair(,res);
}
}; bool seg_inter_line(Line l1,Line l2) //line l1.seg l2;
{
return sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= ;
} const int MAXN = ;
Point up[MAXN],down[MAXN];
int n; int main()
{
while (scanf("%d",&n) != EOF)
{
if (n == ) break;
for (int i = ; i < n ; i++)
{
scanf("%lf%lf",&up[i].x,&up[i].y);
down[i] = up[i];
down[i].y--;
}
bool flag = false;
double ans = -INF;
int k;
for (int i = ; i < n && !flag ; i++)
{
for (int j = i + ; j < n && !flag ; j++)
{
for (k = ; k < n ; k++)
{
if (seg_inter_line(Line(up[i],down[j]),Line(up[k],down[k])) == false)
break;
}
if (k >= n)
{
flag = true;
break;
}
if (k > max(i,j))
{
if (seg_inter_line(Line(up[i],down[j]),Line(up[k - ],up[k])))
{
pair<int,Point>ret = Line(up[i],down[j]) & Line(up[k - ],up[k]);
ans = max(ans,ret.second.x);
}
if (seg_inter_line(Line(up[i],down[j]),Line(down[k - ],down[k])))
{
pair<int,Point>ret = Line(up[i],down[j]) & Line(down[k - ],down[k]);
ans = max(ans,ret.second.x);
}
} for (k = ; k < n ; k++)
{
if (seg_inter_line(Line(down[i],up[j]),Line(down[k],up[k])) == false)
break;
}
if (k >= n)
{
flag = true;
break;
}
if (k > max(i,j))
{
if (seg_inter_line(Line(down[i],up[j]),Line(up[k],up[k - ])) == true)
{
pair<int,Point>ret = Line(down[i],up[j]) & Line(up[k],up[k - ]);
ans = max(ans,ret.second.x);
}
if (seg_inter_line(Line(down[i],up[j]),Line(down[k],down[k - ])) == true)
{
pair<int,Point>ret = Line(down[i],up[j]) & Line(down[k],down[k - ]);
ans = max(ans,ret.second.x);
}
}
}
}
if (flag) puts("Through all the pipe.");
else printf("%.2f\n",ans);
}
return ;
}
POJ 3449 Geometric Shapes
暴力判相交。这里有个知识
**给出坐标轴上1个正方形对角线上的2个点
求另外2个点的最简单方法
这4个方程可解
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b) const
{
return x * b.x + y * b.y;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
}
}; bool inter(Line l1,Line l2)
{
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= &&
sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= ;
} const int MAXN = ;
struct node
{
char id;
int n;
Point p[MAXN];
friend bool operator < (const node &a,const node &b)
{
return a.id < b.id;
}
}src[MAXN]; char str[MAXN];
bool check(node a,node b)
{
for (int i = ; i < a.n ; i++)
{
for (int j = ; j < b.n ; j++)
{
if (inter(Line(a.p[i],a.p[(i + ) % a.n]),Line(b.p[j],b.p[(j + ) % b.n])))
return true;
}
}
return false;
} bool flag[MAXN];
int main()
{
int n;
while (scanf("%s",str) != EOF)
{
if (str[] == '.') break;
n = ;
src[].id = str[];
scanf("%s",str);
if (strcmp(str,"square") == )
{
src[].n = ;
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
src[].p[].x = ((src[].p[].x + src[].p[].x) + (src[].p[].y - src[].p[].y)) / ;
src[].p[].y = ((src[].p[].y + src[].p[].y) + (src[].p[].x - src[].p[].x)) / ;
src[].p[].x = ((src[].p[].x + src[].p[].x) - (src[].p[].y - src[].p[].y)) / ;
src[].p[].y = ((src[].p[].y + src[].p[].y) - (src[].p[].x - src[].p[].x)) / ;
}
else if (strcmp(str,"line") == )
{
src[].n = ;
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
}
else if (strcmp(str,"triangle") == )
{
src[].n = ;
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
}
else if (strcmp(str,"rectangle") == )
{
src[].n = ;
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
scanf(" (%lf,%lf)",&src[].p[].x,&src[].p[].y);
src[].p[].x = src[].p[].x + src[].p[].x - src[].p[].x;
src[].p[].y = src[].p[].y + src[].p[].y - src[].p[].y;
}
else if(strcmp(str,"polygon") == )
{
scanf("%d",&src[].n);
for (int i = ; i <= src[].n ; i++)
scanf(" (%lf,%lf)",&src[].p[i].x,&src[].p[i].y);
}
n = ;
while (scanf("%s",str) != EOF)
{
if (str[] == '-') break;
src[n].id = str[];
scanf("%s",str);
if (strcmp(str,"square") == )
{
src[n].n = ;
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
src[n].p[].x = ((src[n].p[].x + src[n].p[].x) + (src[n].p[].y - src[n].p[].y)) / ;
src[n].p[].y = ((src[n].p[].y + src[n].p[].y) + (src[n].p[].x - src[n].p[].x)) / ;
src[n].p[].x = ((src[n].p[].x + src[n].p[].x) - (src[n].p[].y - src[n].p[].y)) / ;
src[n].p[].y = ((src[n].p[].y + src[n].p[].y) - (src[n].p[].x - src[n].p[].x)) / ;
}
else if (strcmp(str,"line") == )
{
src[n].n = ;
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
}
else if (strcmp(str,"triangle") == )
{
src[n].n = ;
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
}
else if (strcmp(str,"rectangle") == )
{
src[n].n = ;
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
scanf(" (%lf,%lf)",&src[n].p[].x,&src[n].p[].y);
src[n].p[].x = src[n].p[].x + src[n].p[].x - src[n].p[].x;
src[n].p[].y = src[n].p[].y + src[n].p[].y - src[n].p[].y;
}
else if(strcmp(str,"polygon") == )
{
scanf("%d",&src[n].n);
for (int i = ; i <= src[n].n ; i++)
scanf(" (%lf,%lf)",&src[n].p[i].x,&src[n].p[i].y);
}
n++;
}
sort(src,src + n);
for (int i = ; i < n ; i++)
{
printf("%c ",src[i].id);
memset(flag,false,sizeof(flag));
int cnt = ;
for (int j = ; j < n ; j++)
{
if (i == j) continue;
if (check(src[i],src[j]))
{
cnt++;
flag[j] = true;
}
}
if (cnt == ) puts("has no intersections");
else if (cnt == )
{
printf("intersects with ");
for (int j = ; j < n ; j++)
{
if (flag[j])
{
printf("%c\n",src[j].id);
break;
}
}
}
else if (cnt == )
{
printf("intersects with ");
for (int j = ; j < n ; j++)
{
if (flag[j])
{
if(cnt == )printf("%c ",src[j].id);
if(cnt == )printf("and %c\n",src[j].id);
cnt--;
}
}
}
else
{
printf("intersects with ");
for (int j = ; j < n ; j++)
{
if (flag[j])
{
if(cnt > )printf("%c, ",src[j].id);
if(cnt == )printf("and %c\n",src[j].id);
cnt--;
}
}
}
}
puts("");
}
return ;
}
POJ 1584 A Round Peg in a Ground Hole
凸多边形判定通过点到直线距离判园是否在凸多边形内
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b) {return a % b == ? b : gcd(b, a % b);}
const double eps = 1e-;
int sgn(double x)
{
if (fabs(x) < eps) return ;
if (x < ) return -;
return ;
} struct Point
{
double x,y;
Point(){}
Point(double tx,double ty)
{
x = tx;
y = ty;
} Point operator - (const Point &b) const
{
return Point(x - b.x,y - b.y);
} double operator ^ (const Point &b) const
{
return x * b.y - y * b.x;
} double operator * (const Point &b)const
{
return x * b.x + y * b.y;
}
}; struct Line
{
Point s,e;
Line(){}
Line(Point a,Point b)
{
s = a;
e = b;
}
}; double dist(Point a,Point b)
{
return sqrt((b - a) * (b - a));
} //判断凸多边形
//允许共线边
//点可以是顺时针给出也可以是逆时针给出
//点的编号1~n-1
bool isconvex(Point poly[],int n)
{
bool s[];
memset(s,false,sizeof(s));
for(int i = ;i < n;i++)
{
s[sgn( (poly[(i + ) % n]-poly[i]) ^ (poly[(i + ) % n] - poly[i]) ) + ] = true;
if(s[] && s[])return false;
}
return true;
} //点到线段的距离
//返回点到线段最近的点
Point NearestPointToLineSeg(Point P,Line L)
{
Point result;
double t = ((P - L.s)*(L.e - L.s)) / ((L.e - L.s)*(L.e - L.s));
if(t >= && t <= )
{
result.x = L.s.x + (L.e.x - L.s.x) * t;
result.y = L.s.y + (L.e.y - L.s.y) * t;
}
else
{
if(dist(P,L.s) < dist(P,L.e))
result = L.s;
else result = L.e;
}
return result;
} //*判断点在线段上
bool OnSeg(Point P,Line L)
{
return
sgn((L.s-P)^(L.e-P)) == &&
sgn((P.x - L.s.x) * (P.x - L.e.x)) <= &&
sgn((P.y - L.s.y) * (P.y - L.e.y)) <= ;
} //*判断点在凸多边形内
//点形成一个凸包,而且按逆时针排序(如果是顺时针把里面的<0改为>0)
//点的编号:0~n-1
//返回值:
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inConvexPoly(Point a,Point p[],int n)
{
for(int i = ; i < n ; i++)
{
if(sgn((p[i] - a) ^ (p[(i + ) % n] - a)) < )return -;
else if(OnSeg(a,Line(p[i],p[(i + ) % n])))return ;
}
return ;
} bool inter(Line l1,Line l2)
{
return
max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e - l1.e) ^ (l1.s - l1.e)) <= &&
sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e - l2.e) ^ (l2.s - l2.e)) <= ;
} //*判断点在任意多边形内
//射线法,poly[]的顶点数要大于等于3,点的编号0~n-1
//返回值
//-1:点在凸多边形外
//0:点在凸多边形边界上
//1:点在凸多边形内
int inPoly(Point p,Point poly[],int n)
{
int cnt;
Line ray,side;
cnt = ;
ray.s = p;
ray.e.y = p.y;
ray.e.x = -100000000000.0;//-INF,注意取值防止越界 for(int i = ;i < n;i++)
{
side.s = poly[i];
side.e = poly[(i+)%n]; if(OnSeg(p,side))return ; //如果平行轴则不考虑
if(sgn(side.s.y - side.e.y) == )
continue; if(OnSeg(side.s,ray))
{
if(sgn(side.s.y - side.e.y) > )cnt++;
}
else if(OnSeg(side.e,ray))
{
if(sgn(side.e.y - side.s.y) > )cnt++;
}
else if(inter(ray,side))
cnt++;
}
if(cnt % == )return ;
else return -;
} const int MAXN = ;
Point src[MAXN];
int n; int main()
{
double R,X,Y;
while (scanf("%d",&n) != EOF)
{
if (n < ) break;
scanf("%lf%lf%lf",&R,&X,&Y);
for (int i = ; i < n ; i++)
scanf("%lf%lf",&src[i].x,&src[i].y);
if (!isconvex(src,n))
{
printf("HOLE IS ILL-FORMED\n");
continue;
}
Point P = Point(X,Y);
if(inPoly(P,src,n) < )
{
printf("PEG WILL NOT FIT\n");
continue;
}
bool flag = true;
for (int i = ; i < n ; i++)
{
if(sgn(dist(P,NearestPointToLineSeg(P,Line(src[i],src[(i + ) % n]))) - R) < )
{
flag = false;
break;
}
}
if(flag)printf("PEG WILL FIT\n");
else printf("PEG WILL NOT FIT\n");
}
return ;
}
Kuangbin 带你飞-基础计算几何专题 题解的更多相关文章
- Kuangbin 带你飞-线段树专题 题解
HDU 1166 敌兵布阵 单调更新区间查询和 #include <map> #include <set> #include <list> #include < ...
- kuangbin带你飞 并查集 题解
做这套题之前一直以为并查集是很简单的数据结构. 做了才发现自己理解太不深刻.只看重片面的合并集合.. 重要的时发现每个集合的点与这个根的关系,这个关系可以做太多事情了. 题解: POJ 2236 Wi ...
- 【kuangbin带你飞】 MST专题
唉,被班级合唱和复变考试搞得心力交瘁.新算法学不进去,更新下吧 A - Til the Cows Come Home The Head Elder of the tropical island of ...
- 「kuangbin带你飞」专题十四 数论基础
layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...
- 「kuangbin带你飞」专题十二 基础DP
layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathj ...
- [kuangbin带你飞]专题1-23题目清单总结
[kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...
- 「kuangbin带你飞」专题二十 斜率DP
layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...
- 「kuangbin带你飞」专题二十二 区间DP
layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - ku ...
- 「kuangbin带你飞」专题十九 矩阵
layout: post title: 「kuangbin带你飞」专题十九 矩阵 author: "luowentaoaa" catalog: true tags: mathjax ...
随机推荐
- C++内置类型如何存放于计算机内存中
摘要:内置类型的机器实现.字/字节/比特.内存 一.概念 计算机以比特序列存储数据,每个比特非0即1,如:00011011011100010110010000111011... 二.计算机以块来处理内 ...
- DFS——hdu5682zxa and leaf
一.题目回顾 题目链接:zxa and leaf Sample Input 2 3 2 1 2 1 3 2 4 3 9 6 2 1 2 1 3 1 4 2 5 2 6 3 6 5 9 Sample ...
- 详细讲解Java中方法的重载和重写
首先讲讲方法的重载: Java的重载就是在类中可以创建多个方法,它们具有相同的名字,但是却有不同的参数. 判断是否重载只有两个条件: 1)相同的方法名 2)不同的参数 具体为: A.方法参数类型不同 ...
- Android问题:could not install *smartsocket* listener;Address already in use
今天启动genymotion后,发现没有ip地址,运行项目时报错: 可见,没有连接到模拟器,无法运行,而先前说过没有ip,自然而然连接不上, 解决放法:将资源管理器打开,将adb全部退出 ...
- 基于SDN的IP RAN网络虚拟化技术
http://www.zte.com.cn/cndata/magazine/zte_technologies/2014/2014_4/magazine/201404/t20140421_422858. ...
- 【bzoj2956】模积和 数论
题目描述 求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j. 输入 第一行两个数n,m. 输出 一个整数表示答案mod 1994041 ...
- Div+Css中transparent制作奥运五环
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- (转载)Java中如何遍历Map对象的4种方法
在Java中如何遍历Map对象 How to Iterate Over a Map in Java 在java中遍历Map有不少的方法.我们看一下最常用的方法及其优缺点. 既然java中的所有map都 ...
- [NOI2017 D1T1]整数
题目大意:有一个整数 $x$ ,一开始为 $0$ .有 $n$ 个操作,有两种类型: $1 \;a\; b$:将 $x$ 加上整数 $a\cdot 2^b$ ,其中 $a$ 为一个整数, $b$ 为一 ...
- Vim使用小记(一)常用操作
By francis_hao Sep 22,2016 vim的功能自然不止如此,这里只是把日常使用频率较高的记录下来,若想了解vim的全部功能可查阅其帮助手册:help,或者查询指定命令的用法: ...