【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 }
【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 }
【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; }