【kuangbin专题】计算几何基础


【POJ 2318】 TOYS

【题目大意】

给定 n 条直线,m个玩具,每两个直线之间是一个隔间,一个玩具有一个坐标,问一个隔间内有多少个玩具

【题目思路】

暴力枚举,每读入一个点,扫一遍所有边,判断这个点是不是在两边之间,如果在,就给当前边的答案

1 bool is_midd(P a, L b, L c)
2 {//分别求点a 和 b,c的叉乘,判断他是在直线的左边还是右边
//如果两者异号,,则说明两边分别在点的不同方向
3 int x = cmp(cross(a - b.s, b.t - b.s)),
y = cmp(cross(a - c.s, c.t - c.s)); 4 return x * y <= 0; 5 6 }

【代码】

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<queue>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<cmath>
  8 using namespace std;
  9 const double eps = 1e-6;
 10 const int    MAXN = 20010;
 11 const double lim = 10000;
 12 const double PI = acos(-1.0);
 13 int n, m;
 14 inline int cmp(double x)
 15 {
 16     if (x > eps)return 1;
 17     return x < -eps ? -1 : 0;
 18 }
 19 struct V
 20 {
 21     int x, y;
 22     double ang;
 23     double angle()
 24     {//求取极角
 25         return atan2(y, x);
 26     }
 27     V(int X = 0,int Y = 0)
 28     {
 29         //初始化
 30         x = X, y = Y;
 31     }
 32     bool operator ==(const V &b)
 33     {
 34         return cmp(x - b.x) && cmp(y - b.y);
 35     }
 36 
 37 };
 38 typedef V  P;
 39 V operator +(V a, V b) { return V(a.x + b.x, a.y + b.y); }
 40 V operator -(V a, V b) { return V(a.x - b.x, a.y - b.y); }
 41 V operator *(V a, double b) { return V(a.x *b, a.y*b); }
 42 V operator /(V a, double b) { return V(a.x / b, a.y / b); }
 43 struct L
 44 {
 45     P s, t;
 46     double ang;
 47     L(P X = V(), P Y = V())
 48     {
 49         s = X, t = Y; 
 50     }
 51 };
 52 typedef L S;
 53 double cross(V a, V b)
 54 {
 55     return 1.0*a.x*b.y - 1.0*a.y*b.x;
 56 }
 57 bool is_midd(P a, L b, L c)
 58 {
 59     int x = cmp(cross(a - b.s, b.t - b.s)), y = cmp(cross(a - c.s, c.t - c.s));
 60     return x * y <= 0;
 61 
 62 }
 63 P p[MAXN];
 64 L l[MAXN];
 65 int ans[MAXN];
 66 int main()
 67 {
 68     int n, m, x1, y1, x2, y2;
 69     while (scanf("%d", &n))
 70     {
 71         if (n == 0)
 72             break;
 73         scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
 74         l[0].s = P(x1, y2), l[0].t = P(x1, y1);
 75         l[n + 1].s = P(x2, y2), l[n + 1].t = P(x2, y1);
 76         for (int i = 1; i <= n; i++)
 77         {
 78             int u, v;
 79             scanf("%d%d", &u, &v);
 80             l[i].s = P(v, y2), l[i].t = P(u, y1);
 81         }
 82         memset(ans, 0, sizeof(ans));
 83         int temp = 0;
 84         for (int i = 1; i <= m; i++)
 85         {
 86             int x, y;
 87             scanf("%d%d", &x, &y);
 88             P tmp = P(x, y);
 89             for (int j = 0; j <= n; j++)
 90             {
 91                 if (is_midd(tmp,l[j],l[j+1]))
 92                 {
 93                     
 94                     ans[j]++;
 95                     break;
 96                 }
 97             }
 98         }
 99         for (int i = 0; i <= n; i++)
100             printf("%d: %d\n", i, ans[i]);
101         printf("\n");
102     }
103     return 0;
104 }
View Code

【POJ  3304】Segments

【题目大意】

给定 n 条线段,判断是否存在一个线段使他们投影在那条线端上的投影有交点,有输出“Yes”,无输出“No”

【题目分析】

 思考下对于这个几何问题,投影的话可以看作从一条直线上对要投影的直线进行投影

所以,对投影区域的直线做一条垂直的直线,而这条直线就能够和所有直线相交,所以问题可以简化为

(以上说明变成几何形状放在脑子里面思考一下)

是否存在一条直线,能够和给定的所有直线相交

一条直线能够和所有直线相交的情况,最极端的看作,如果这条直线和线段端点有交点,则可以进行缩减

如果没有,因为已经到了端点,继续转必然导致无法相交

所以只需要判断各个直线的端点即可

 
 
double cross(V a, V b)
{ return a.x*b.y - a.y*b.x; } double cross(P a, P b, P c) { return cross(b-a, c-a); }
bool L_is_Inter(L a, L b)
{
  //分别判断线段 b的起始点和终止点在 线段 a 的左侧还是右侧
//如果在不同侧的话,就说明两个线段相交
return cmp(cross(b.s, a.s, a.t))*cmp(cross(b.t, a.s, a.t)) <= 0; } 

【代码】

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<queue>
  5 #include<iostream>
  6 #include<algorithm>
  7 #include<cmath>
  8 #define cmp sgn
  9 using namespace std;
 10 const double eps = 1e-8;
 11 const int    MAXN = 110;
 12 const double lim = 10000;
 13 const double PI = acos(-1.0);
 14 int n, m;
 15 inline int sgn(double x)
 16 {
 17     if (x > eps)return 1;
 18     return x < -eps ? -1 : 0;
 19 }
 20 struct V
 21 {
 22     double x, y;
 23     double ang;
 24     double angle()
 25     {//求取极角
 26         return atan2(y, x);
 27     }
 28     V(double X = 0, double Y = 0)
 29     {
 30         //初始化
 31         x = X, y = Y;
 32         ang = atan2(y, x);
 33     }
 34     bool operator ==(const V &b)
 35     {
 36         return cmp(x - b.x) && cmp(y - b.y);
 37     }
 38 
 39 };
 40 typedef V  P;
 41 V operator +(V a, V b) { return V(a.x + b.x, a.y + b.y); }
 42 V operator -(V a, V b) { return V(a.x - b.x, a.y - b.y); }
 43 V operator *(V a, double b) { return V(a.x *b, a.y*b); }
 44 double operator *(V a, V b) { return a.x*b.x+a.y*b.y; }
 45 V operator /(V a, double b) { return V(a.x / b, a.y / b); }
 46 struct L
 47 {
 48     P s, t;
 49     double ang;
 50     L(P X = V(), P Y = V())
 51     {
 52         s = X, t = Y, ang = (Y - X).angle();
 53     }
 54 };
 55 typedef L S;
 56 double cross(V a, V b)
 57 {
 58     return a.x*b.y - a.y*b.x;
 59 }
 60 double cross(P a, P b, P c)
 61 {
 62     
 63     return cross(b-a, c-a);
 64 }
 65 bool L_is_Inter(L a, L b)
 66 {
 67     return cmp(cross(b.s, a.s, a.t))*cmp(cross(b.t, a.s, a.t)) <= 0;
 68 }
 69 P p[MAXN];
 70 L l[MAXN];
 71 
 72 bool check(P b,P c)
 73 {
 74     L a = L(b, c);
 75     if (sgn(dis(a.s, a.t)) == 0)return false;
 76     for(int i=1;i<=n;i++)
 77         if (!L_is_Inter(a, l[i]))
 78         {
 79             return false;
 80         }
 81     return true;
 82 }
 83 int main()
 84 {
 85     int T;
 86     scanf("%d", &T);
 87     while (T--)
 88     {
 89         bool flag = false;
 90         scanf("%d", &n);
 91         for (int i = 1; i <= n; i++)
 92         {
 93             scanf("%lf%lf%lf%lf", &l[i].s.x, &l[i].s.y,&l[i].t.x,&l[i].t.y);
 94         }
 95         for(int i=1;i<=n;i++)
 96             for (int j = 1; j <= n; j++)
 97             {
 98                 if (check(l[i].s, l[j].s) || check(l[i].s, l[j].t) || check(l[i].t, l[j].t) || check(l[i].t, l[j].s))
 99                 {
100                     flag = true;
101                     break;
102                 }
103                 if (flag)
104                     break;
105             }
106         if (flag)
107             printf("Yes!\n");
108         else
109             printf("No!\n");
110     }
111     return 0;
112 }
View Code

【POJ  1269】Intersecting Lines

【题目大意】

 给定n组线段,每组有两个线段,判断他们是否相交,如果相交输出交点,没有输出“NONE”,重合输出 “LINE”

【题目分析】

计算几何基础知识裸题,考察计算几何知识

【代码】


Source Code

Problem: 3304   User: deviljor
Memory: 672K   Time: 969MS
Language: G++   Result: Accepted
    • Source Code
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<iostream>
#include<algorithm>
#include<cmath>
#define cmp sgn
using namespace std;
const double eps = 1e-8;
const int    MAXN = 110;
const double lim = 10000;
const double PI = acos(-1.0);
int n, m;
inline int sgn(double x)
{
	if (x > eps)return 1;
	return x < -eps ? -1 : 0;
}
structV
{
	double x, y;
	double ang;
	double angle()
	{//求取极角
		return atan2(y, x);
	}
	V(double X = 0, double Y = 0)
	{
		//初始化
		x = X, y = Y;
		ang = atan2(y, x);
	}
	bool operator ==(const V &b)
	{
		return cmp(x - b.x) && cmp(y - b.y);
	}

};
typedef V  P;
V operator +(V a, V b) { return V(a.x + b.x, a.y + b.y); }
V operator -(V a, V b) { return V(a.x - b.x, a.y - b.y); }
V operator *(V a, double b) { return V(a.x *b, a.y*b); }
double operator *(V a, V b) { return a.x*b.x+a.y*b.y; }
V operator /(V a, double b) { return V(a.x / b, a.y / b); }
structL
{
	P s, t;
	double ang;
	L(P X = V(), P Y = V())
	{
		s = X, t = Y, ang = (Y - X).angle();
	}
};
typedef L S;
double cross(V a, V b)
{
	return a.x*b.y - a.y*b.x;
}
double cross(P a, P b, P c)
{
	
	return cross(b-a, c-a);
}
bool operator <(const L &a, const L &b)
{
	double r = a.ang - b.ang;
	if (cmp(r) != 0)    return cmp(r) == -1;
	//极角相同,默认偏下的更大
	return cmp(cross(a.t - a.s, b.t - a.s)) == -1;
}
double dot(V a, V b)
{
	return a.x*b.x + a.y*b.y;
}
double dis(P a, P b)
{
	return sqrt((b-a)*(b-a));

}
bool is_parallel(L a, L b)
{
	return cmp(cross(a.t - a.s, b.t - b.s)) == 0;
}
bool L_is_Inter(L a, L b)
{
	return cmp(cross(b.s, a.s, a.t))*cmp(cross(b.t, a.s, a.t)) <= 0;
}
P p[MAXN];
L l[MAXN];

bool check(P b,P c)
{
	L a = L(b, c);
	if (sgn(dis(a.s, a.t)) == 0)return false;
	for(int i=1;i<=n;i++)
		if (!L_is_Inter(a, l[i]))
		{
			return false;
		}
	return true;
}
int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		bool flag = false;
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
		{
			scanf("%lf%lf%lf%lf", &l[i].s.x, &l[i].s.y,&l[i].t.x,&l[i].t.y);
		}
		for(int i=1;i<=n;i++)
			for (int j = 1; j <= n; j++)
			{
				if (check(l[i].s, l[j].s) || check(l[i].s, l[j].t) || check(l[i].t, l[j].t) || check(l[i].t, l[j].s))
				{
					flag = true;
					break;
				}
				if (flag)
					break;
			}
		if (flag)
			printf("Yes!\n");
		else
			printf("No!\n");
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/rentu/p/11608189.html
今日推荐