链接:https://cn.vjudge.net/contest/68968
题意:m个玩具落在n+1个区间,给你玩具的坐标,问每个区间有多少玩具。
思路:叉积的简单应用,用叉积判断在直线的哪一侧,因为是顺序给出坐标,所以从左往右判断即可。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 5e3 + 5; 6 int U[maxn], L[maxn], ans[maxn]; 7 int Cross(int x1, int y1, int x2, int y2) 8 { 9 return x1 * y2 - x2 * y1; 10 } 11 int main() 12 { 13 int n, m, x1, y1, x2, y2; 14 int a, b; 15 while(~scanf("%d",&n) && n) 16 { 17 scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2); 18 for(int i = 0;i < n;i++) 19 { 20 scanf("%d %d",&U[i], &L[i]); 21 } 22 for(int i = 0;i <= n;i++) ans[i] = 0; 23 while(m--) 24 { 25 scanf("%d%d",&a, &b); 26 int i = 0; 27 for(i = 0;i < n;i++) 28 { 29 if(Cross(a - L[i], b - y2, U[i] - L[i], y1 - y2) <= 0) break; 30 } 31 ans[i]++; 32 } 33 for(int i = 0;i <= n;i++) printf("%d: %d\n",i, ans[i]); 34 printf("\n"); 35 } 36 return 0; 37 }
题意:同上一题类似,不过需要排序和改变输出。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 5e3 + 5; 6 int U[maxn], L[maxn], ans[maxn], num[maxn]; 7 int Cross(int x1, int y1, int x2, int y2) 8 { 9 return x1 * y2 - x2 * y1; 10 } 11 int main() 12 { 13 int n, m, x1, y1, x2, y2; 14 int a, b; 15 while(~scanf("%d",&n) && n) 16 { 17 scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2); 18 for(int i = 0;i < n;i++) 19 { 20 scanf("%d %d",&U[i], &L[i]); 21 } 22 sort(U, U + n); 23 sort(L, L + n); 24 for(int i = 0;i <= n;i++) ans[i] = num[i] = 0; 25 while(m--) 26 { 27 scanf("%d%d",&a, &b); 28 int i = 0; 29 for(i = 0;i < n;i++) 30 { 31 if(Cross(a - L[i], b - y2, U[i] - L[i], y1 - y2) <= 0) break; 32 } 33 num[i]++; 34 } 35 for(int i = 0;i <= n;i ++) ans[num[i]] ++; 36 printf("Box\n"); 37 for(int i = 1;i <= n;i++)if(ans[i]) printf("%d: %d\n",i, ans[i]); 38 } 39 return 0; 40 }
题意:给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。
思路:枚举所有端点,判断与其他线段相不相交,至于为什么,画个图吧,反正我理解挺久的。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 const double eps = 1e-8; 5 struct Point{ 6 double x, y; 7 Point(double _x = 0, double _y = 0):x(_x),y(_y){} 8 }; 9 double Multi(Point p1, Point p2, Point p0) { 10 return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x); 11 } 12 int n; 13 struct Line{ 14 Point a, b; 15 }; 16 Line line[1000]; 17 bool check(Point a, Point b) 18 { 19 if(fabs(a.x - b.x) < eps && fabs(a.y - b.y) < eps) return false; 20 for(int i = 0;i < n;i++) 21 { 22 if (Multi(line[i].a, b, a) * Multi(line[i].b, b, a) > 0) return false; 23 24 } 25 return true; 26 } 27 int main() 28 { 29 int t; 30 scanf("%d",&t); 31 while(t--) 32 { 33 scanf("%d",&n); 34 double x1, y1, x2, y2; 35 for(int i = 0;i < n;i++) 36 { 37 scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); 38 line[i].a = Point(x1, y1); 39 line[i].b = Point(x2, y2); 40 } 41 if(n == 1){ printf("Yes!\n");continue;} 42 bool flag = false; 43 for(int i = 0;i < n && !flag;i++) 44 { 45 if (check(line[i].a, line[i].b)) flag = true; 46 for(int j = i + 1;j < n && !flag;j++) 47 { 48 if(check(line[i].a, line[j].a) || 49 check(line[i].a, line[j].b) || 50 check(line[i].b, line[j].a) || 51 check(line[i].b, line[j].b)) 52 flag = true; 53 } 54 } 55 if(flag) printf("Yes!\n"); 56 else printf("No!\n"); 57 } 58 return 0; 59 }
题意:俩条直线相交,相交则输出交点。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 using namespace std; 4 const double eps = 1e-8; 5 struct Point{ 6 double x, y; 7 Point(double _x = 0, double _y = 0):x(_x),y(_y){} 8 }a, b, c, d; 9 typedef Point Vector; 10 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } 11 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } 12 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } 13 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 14 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//叉积 15 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){ 16 Vector u = P - Q; 17 double t = Cross(w,u)/Cross(v,w); 18 return P + v*t; 19 } 20 int main() 21 { 22 int n; 23 scanf("%d",&n); 24 printf("INTERSECTING LINES OUTPUT\n"); 25 while(n--) 26 { 27 scanf("%lf %lf %lf %lf",&a.x, &a.y, &b.x, &b.y); 28 scanf("%lf %lf %lf %lf",&c.x, &c.y, &d.x, &d.y); 29 if(Cross(a - c, b - c) == 0 && Cross(a - d, b - d) == 0) 30 printf("LINE\n"); 31 else if(Cross(a - b, c- d) == 0) 32 printf("NONE\n"); 33 else 34 { 35 Point p = GetLineIntersection(a, a-b, c, c-d); 36 printf("POINT %.2f %.2f\n",p.x,p.y); 37 } 38 } 39 printf("END OF OUTPUT\n"); 40 return 0; 41 }
题意:问你从(0,5) - > (10, 5)的最短路。
思路:枚举所有端点,如果确定和其他线段不规范相交,则加入这条路径,然后拿Floyd去跑最短路即可。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const double eps = 1e-6; 7 const int maxn = 1e3 + 5; 8 const double inf = 1e20; 9 struct Point{ 10 double x, y; 11 Point(double _x = 0, double _y = 0):x(_x),y(_y){} 12 }; 13 typedef Point Vector; 14 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } 15 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } 16 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } 17 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 18 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý 19 int dcmp(double x){ 20 if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; 21 } 22 double distant(Point a, Point b){ 23 double x = a.x - b.x; 24 double y = a.y - b.y; 25 return sqrt(x*x + y*y); 26 } 27 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) 28 { 29 double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1), 30 c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1); 31 return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0; 32 } 33 struct edge{ 34 Point from, to; 35 edge(){} 36 edge(Point a, Point b){ from = a,to = b;} 37 }; 38 Point p[maxn]; 39 edge e[maxn]; 40 double d[maxn][maxn]; 41 int n, tot, cnt; 42 bool check(Point a, Point b) 43 { 44 for(int i = 0;i < tot;i++) 45 if(SegmentProperIntersection(a, b, e[i].from, e[i].to)) 46 { 47 return false; 48 } 49 50 return true; 51 } 52 int main() 53 { 54 while(~scanf("%d",&n) && n != -1) 55 { 56 tot = cnt = 0; 57 double x, y1, y2, y3, y4; 58 p[cnt++] = Point(0, 5); 59 for(int i = 0;i < n;i++) 60 { 61 scanf("%lf%lf%lf%lf%lf",&x, &y1, &y2, &y3, &y4); 62 p[cnt++] = Point(x, y1); 63 p[cnt++] = Point(x, y2); 64 p[cnt++] = Point(x, y3); 65 p[cnt++] = Point(x, y4); 66 e[tot++] = edge(Point(x, 0), Point(x, y1)); 67 e[tot++] = edge(Point(x, y2), Point(x, y3)); 68 e[tot++] = edge(Point(x, y4), Point(x, 10)); 69 } 70 p[cnt++] = Point(10, 5); 71 for(int i = 0;i < cnt;i++) 72 for(int j = 0;j < cnt;j++) 73 d[i][j] = inf; 74 for(int i = 0; i < cnt;i++) 75 { 76 for(int j = i + 1;j < cnt;j ++) 77 { 78 if(fabs(p[i].x - p[j].x)< eps)continue; 79 if(check(p[i], p[j])) 80 { 81 d[i][j] = d[j][i] = distant(p[i], p[j]); 82 } 83 } 84 } 85 for(int k = 0;k < cnt;k++) 86 for(int i = 0;i < cnt;i++) 87 for(int j = 0;j < cnt;j++) 88 d[i][j] = min(d[i][j], d[i][k] + d[k][j]); 89 printf("%.2f\n",d[0][cnt - 1]); 90 } 91 return 0; 92 }
题意:筷子一根一根丢,问哪些筷子没被压着。
思路:所有和新加入的线段规范相交的线段标记,最后未标记的输出。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const double eps = 1e-8; 7 const int maxn = 1e5 + 5; 8 const double inf = 1e20; 9 struct Point{ 10 double x, y; 11 Point(double _x = 0, double _y = 0):x(_x),y(_y){} 12 }; 13 typedef Point Vector; 14 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } 15 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } 16 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } 17 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 18 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý 19 int dcmp(double x){ 20 if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; 21 } 22 double distant(Point a, Point b){ 23 double x = a.x - b.x; 24 double y = a.y - b.y; 25 return sqrt(x*x + y*y); 26 } 27 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) 28 { 29 double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1), 30 c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1); 31 return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0; 32 } 33 struct Line{ 34 Point from, to; 35 Line(){} 36 Line(Point a, Point b){ from = a,to = b;} 37 }; 38 Line line[maxn]; 39 bool check(Line a, Line b) 40 { 41 return SegmentProperIntersection(a.from, a.to, b.from, b.to); 42 } 43 int vis[maxn]; 44 int n, tot, cnt; 45 int main() 46 { 47 while(~scanf("%d",&n) && n) 48 { 49 double x1, y1, x2, y2; 50 for(int i = 0;i < n;i++) 51 { 52 scanf("%lf %lf %lf %lf",&x1, &y1, &x2, &y2); 53 line[i] = Line( Point(x1, y1), Point(x2, y2) ); 54 vis[i] = 0; 55 } 56 for(int i = 0;i < n;i++){ 57 for(int j = i + 1;j < n;j++) 58 { 59 if(check(line[i], line[j])) 60 { 61 vis[i] = 1;break; 62 } 63 } 64 } 65 printf("Top sticks: "); 66 bool flag = true; 67 for(int i = 0;i < n;i++) 68 { 69 if(!vis[i]) 70 { 71 if(flag) flag = false; 72 else printf(", "); 73 printf("%d",i + 1); 74 } 75 } 76 printf(".\n"); 77 } 78 return 0; 79 }
题意:给你一个房间,房间内有很多墙,再给你个宝藏的坐标,你将从外面砸墙而入,问:你炸墙进去通过的最少的墙的1数目是多少。
思路:枚举线段的端点和宝藏位置的连线,看看和几个线段相交,要加上最外围的墙,所以ans从1开始。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const double eps = 1e-8; 7 const int maxn = 1e5 + 5; 8 const int inf = 0x3f3f3f3f; 9 struct Point{ 10 double x, y; 11 Point(double _x = 0, double _y = 0):x(_x),y(_y){} 12 }; 13 typedef Point Vector; 14 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } 15 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } 16 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } 17 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 18 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý 19 int dcmp(double x){ 20 if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; 21 } 22 double distant(Point a, Point b){ 23 double x = a.x - b.x; 24 double y = a.y - b.y; 25 return sqrt(x*x + y*y); 26 } 27 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) 28 { 29 double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1), 30 c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1); 31 return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0; 32 } 33 struct Line{ 34 Point from, to; 35 Line(){} 36 Line(Point a, Point b){ from = a,to = b;} 37 }; 38 Point p[maxn]; 39 Line line[maxn]; 40 int vis[maxn]; 41 int n, tot, cnt; 42 int check(Point b, Point a) 43 { 44 int ans = 1; 45 for(int i = 0;i < tot;i++) 46 { 47 if(SegmentProperIntersection(line[i].from, line[i].to, b, a)) 48 ans ++; 49 } 50 return ans; 51 } 52 int main() 53 { 54 while(~scanf("%d",&n)) 55 { 56 if(n == 0) 57 { 58 printf("Number of doors = 1\n");return 0; 59 } 60 double x1, x2, y1, y2; 61 double x, y; 62 tot = cnt = 0; 63 int ans = inf; 64 for(int i = 0;i < n;i++) 65 { 66 scanf("%lf %lf %lf %lf",&x1 ,&y1, &x2, &y2); 67 p[cnt++] = Point(x1, y1); 68 p[cnt++] = Point(x2, y2); 69 line[tot++] = Line(Point(x1, y1), Point(x2, y2)); 70 } 71 scanf("%lf %lf",&x, &y); 72 Point A = Point(x, y); 73 for(int i = 0;i < cnt;i++) 74 { 75 ans = min(ans, check(A, p[i])); 76 } 77 printf("Number of doors = %d\n",ans); 78 } 79 return 0; 80 }
题意:问直线和矩形是否相交。
思路:这题有坑,这矩形居然是实的,所以要特判一些情况。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const double eps = 1e-8; 7 const int maxn = 1e5 + 5; 8 const int inf = 0x3f3f3f3f; 9 struct Point{ 10 double x, y; 11 Point(double _x = 0, double _y = 0):x(_x),y(_y){} 12 }; 13 typedef Point Vector; 14 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } 15 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } 16 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } 17 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 18 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý 19 double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }//点积 20 int dcmp(double x){ 21 if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; 22 } 23 double distant(Point a, Point b){ 24 double x = a.x - b.x; 25 double y = a.y - b.y; 26 return sqrt(x*x + y*y); 27 } 28 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2) 29 { 30 double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1), 31 c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1); 32 return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0; 33 } 34 struct Line{ 35 Point from, to; 36 Line(){} 37 Line(Point a, Point b){ from = a,to = b;} 38 }; 39 bool check(Line a, Line b){ 40 return SegmentProperIntersection(a.from, a.to, b.from, b.to); 41 } 42 bool OnSegment(Point p, Point a1, Point a2){//判断端点在线段上 43 return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p,a2 - p)) < 0; 44 } 45 bool check2(Point b, Line a){ 46 return OnSegment(b, a.from, a.to); 47 } 48 int n; 49 int main() 50 { 51 scanf("%d",&n); 52 double x1, y1, x2, y2; 53 double x3, y3, x4, y4; 54 while(n--) 55 { 56 bool flag = false; 57 scanf("%lf %lf %lf %lf",&x1, &y1, &x2, &y2); 58 Point E = Point(x1, y1); 59 Point F = Point(x2, y2); 60 Line L = Line(E, F); 61 scanf("%lf %lf %lf %lf",&x3, &y3, &x4, &y4); 62 if(x3 > x4) swap(x3, x4); 63 if(y3 < y4) swap(y3, y4); 64 Point A = Point(x3, y3); 65 Point B = Point(x3, y4); 66 Point C = Point(x4, y4); 67 Point D = Point(x4, y3); 68 Line AB = Line(A, B); 69 Line CB = Line(C, B); 70 Line CD = Line(C, D); 71 Line AD = Line(A, D); 72 if(x1 >= x3 && x1 <= x4 && y1 <= y3 && y1 >= y4) flag = true; 73 if(check(AB, L) || check(CD, L) || check(AD, L) || check(CB, L)) 74 flag = true; 75 if(check2(A, L) || check2(B, L) || check2(C, L) || check2(D, L)) 76 flag = true; 77 if(check2(E, AB) || check2(E, CD) || check2(E, AD) || check2(E, CB)) 78 flag = true; 79 if(check2(F, AB) || check2(F, CD) || check2(F, AD) || check2(F, CB)) 80 flag = true; 81 if(flag) printf("T\n"); 82 else printf("F\n"); 83 } 84 return 0; 85 }
题意:一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.
思路:这题用极角排序,边排序边输出orz。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const double eps = 1e-8; 7 const int maxn = 1e3+ 5; 8 const int inf = 0x3f3f3f3f; 9 struct Point{ 10 double x, y; 11 int num; 12 Point(double _x = 0, double _y = 0):x(_x),y(_y){} 13 }; 14 typedef Point Vector; 15 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); } 16 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } 17 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } 18 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 19 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý 20 double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }//点积 21 int dcmp(double x){ 22 if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; 23 } 24 double distant(Point a, Point b){ 25 double x = a.x - b.x; 26 double y = a.y - b.y; 27 return sqrt(x*x + y*y); 28 } 29 Point p[maxn]; 30 int pos; 31 bool cmp(const Point a, const Point b){ 32 int temp = Cross(p[pos] - a,p[pos] - b); 33 if(temp > 0) return true; 34 else if(temp == 0 && distant(p[pos], a) < distant(p[pos], b)) 35 return true; 36 return false; 37 } 38 int n; 39 int main() 40 { 41 int t; 42 scanf("%d",&t); 43 while (t--){ 44 scanf("%d",&n); 45 for (int i = 0; i < n; ++i) { 46 scanf("%d %lf %lf",&p[i].num, &p[i].x, &p[i].y); 47 if(p[i].y < p[0].y || (p[i].y == p[0].y && p[i].x < p[0].x)) 48 swap(p[i],p[0]); 49 } 50 pos = 0; 51 printf("%d",n); 52 for(int i = 1;i < n;++i){ 53 sort(p + i,p + n, cmp); 54 pos++; 55 } 56 for (int i = 0; i < n; ++i) { 57 printf(" %d",p[i].num); 58 } 59 printf("\n"); 60 } 61 return 0; 62 }
思路:这题在网上扒了一个不是几何的做法,具体看代码吧。
AC代码:
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 const int maxn = 505; 7 struct node{ 8 int l, r, len; 9 }; 10 node a[maxn]; 11 int n; 12 int main() 13 { 14 while(~scanf("%d",&n) && n) 15 { 16 memset(a,0,sizeof(a)); 17 for(int i = 0;i < n;i++) 18 { 19 scanf("%d",&a[i].len); 20 for(int j = 0;j < i;j ++) 21 { 22 a[i].l = max(a[i].l, a[j].r - abs(a[i].len - a[j].len)); 23 } 24 a[i].r = a[i].l + 2*a[i].len; 25 } 26 for(int i = 0;i < n;i++) 27 { 28 for(int j = 0;j < i;j ++) 29 { 30 if(a[i].l < a[j].r) 31 { 32 if(a[j].len < a[i].len) a[j].r = a[i].l; 33 else a[i].l = a[j].r; 34 } 35 } 36 } 37 bool flag = false; 38 for(int i = 0;i < n;i++) 39 { 40 if(a[i].l < a[i].r) 41 { 42 if(!flag) printf("%d",i + 1),flag = true; 43 else printf(" %d",i+1); 44 } 45 } 46 printf("\n"); 47 } 48 return 0; 49 }
题意:两根木棍,摆放的方式由题目给出,问接到雨水的量是多少。(注意是平面,只要考虑面积)
思路:这题不看题解真想不到,简直天坑,点题解一看图就懂了,太多特殊情况了。最后所有都特判了,结果答案还要加个eps才能过orz,醉了!
AC代码:
1 #include<cmath> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const double eps = 1e-12; 6 int sgn(double x){ 7 if(fabs(x) < eps) return 0; 8 else return x < 0 ? -1 : 1; 9 } 10 struct Point{ 11 double x, y; 12 Point(){} 13 Point(double _x, double _y){ 14 x = _x, y = _y; 15 } 16 Point operator - (const Point &b){ 17 return Point(x - b.x, y - b.y); 18 } 19 double operator * (const Point &b){ 20 return x*b.x + y*b.y; 21 } 22 double operator ^ (const Point &b){ 23 return x*b.y - y* b.x; 24 } 25 }; 26 struct Line{ 27 Point s, e; 28 Line(){} 29 Line(Point _s, Point _e){ 30 s = _s, e = _e; 31 } 32 int segcrossing(Line v) 33 { 34 int d1 = sgn((e - s)^(v.s - s)); 35 int d2 = sgn((e - s)^(v.e - s)); 36 int d3 = sgn((v.e - v.s)^(s - v.s)); 37 int d4 = sgn((v.e - v.s)^(e - v.s)); 38 if( (d1^d2) == -2 && (d3^d4) == -2 )return 2; 39 return 40 (d1 == 0 && sgn((v.s - s)*(v.s - e)) <= 0) || 41 (d2 == 0 && sgn((v.e - s)*(v.e - e)) <= 0) || 42 (d3 == 0 && sgn((s - v.s)*(s - v.e)) <= 0) || 43 (d4 == 0 && sgn((e - v.s)*(e - v.e)) <= 0); 44 } 45 Point crosspoint(Line v){ 46 double a1 = (v.e - v.s)^(s - v.s); 47 double a2 = (v.e - v.s)^(e - v.s); 48 return Point((s.x*a2 - e.x*a1)/(a2 - a1),(s.y*a2 - e.y*a1)/(a2 - a1)); 49 } 50 }; 51 int main() 52 { 53 double x1, x2, x3, x4, y1, y2, y3, y4; 54 Line A, B; 55 int t; 56 scanf("%d",&t); 57 while(t--){ 58 scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); 59 scanf("%lf%lf%lf%lf", &x3, &y3, &x4, &y4); 60 A = Line(Point(x1, y1),Point(x2, y2)); 61 B = Line(Point(x3, y3),Point(x4, y4)); 62 if(sgn(A.s.y - A.e.y) == 0 || sgn(B.s.y - B.e.y) == 0) 63 { 64 printf("0.00\n"); 65 continue; 66 } 67 if(sgn((A.s - A.e)^(B.s - B.e)) == 0) 68 { 69 printf("0.00\n"); 70 continue; 71 } 72 //高的点放 s.y下面会用到 73 if(sgn(A.s.y - A.e.y) < 0) swap(A.s, A.e); 74 if(sgn(B.s.y - B.e.y) < 0) swap(B.s, B.e); 75 76 if(A.segcrossing(B) == 0) 77 { 78 printf("0.00\n"); 79 continue; 80 } 81 //口被封掉的情况 82 if(B.segcrossing(Line(A.s,Point(A.s.x,100000))) ) 83 { 84 printf("0.00\n"); 85 continue; 86 } 87 if(A.segcrossing(Line(B.s,Point(B.s.x,100000))) ) 88 { 89 printf("0.00\n"); 90 continue; 91 } 92 Point C = A.crosspoint(B); 93 //printf("%f %f",C.x,C.y); 94 double ans1,ans2; 95 Point D = A.crosspoint(Line(Point(100000,B.s.y),B.s)); 96 //printf("%f %f",D.x,D.y); 97 ans1 = fabs( (B.s - C) ^ (D - C) )/2.0; 98 Point E = B.crosspoint(Line(Point(100000,A.s.y),A.s)); 99 ans2 = fabs( (A.s - C) ^ (E - C) )/2.0; 100 double ans = min(ans1,ans2); 101 printf("%.2f\n",ans +eps); 102 } 103 return 0; 104 }
题意:有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x1,y1),(x1,y1-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道。
思路:因为WA到自闭。于是改用kuangbin大佬的板子,于是就过了,orz!板子很重要。能到达最远的光线一定是某一上端点和某一下端点的连线,枚举判断。
AC代码:
1 #include<cmath> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const double eps = 1e-8; 6 const int maxp = 50; 7 int sgn(double x){ 8 if(fabs(x) < eps) return 0; 9 else return x < 0 ? -1 : 1; 10 } 11 struct Point{ 12 double x, y; 13 Point(){} 14 Point(double _x, double _y){ 15 x = _x, y = _y; 16 } 17 Point operator -(const Point &b)const{ 18 return Point(x - b.x, y - b.y); 19 } 20 double operator *(const Point &b)const{ 21 return x*b.x + y*b.y; 22 } 23 double operator ^(const Point &b)const{ 24 return x*b.y - y*b.x; 25 } 26 bool operator == (Point b) const{ 27 return sgn(x - b.x) == 0 && sgn(y - b.y) == 0; 28 } 29 bool operator < (Point b)const{ 30 return sgn(x - b.x) == 0 ? sgn(y - b.y < 0) : x < b.x; 31 } 32 }; 33 struct Line{ 34 Point s, e; 35 Line(){} 36 Line(Point _s, Point _e){s = _s, e = _e;} 37 bool operator == (Line v){ 38 return (s == v.s) && (e == v.e); 39 } 40 int linecrossing(Line v){ 41 int d1 = sgn((e - s) ^ (v.s - s)); 42 int d2 = sgn((e - s) ^ (v.e - s)); 43 if( (d1 ^ d2) == -2) return 2; 44 else return (d1 == 0) || (d2 == 0); 45 } 46 Point crosspoint(Line v){ 47 double a1 = (v.e - v.s)^(s - v.s); 48 double a2 = (v.e - v.s)^(e - v.s); 49 return Point((s.x*a2 - e.x*a1)/(a2 - a1),(s.y*a2 - e.y*a1)/(a2 - a1)); 50 } 51 }; 52 Point up[maxp], down[maxp]; 53 int main() 54 { 55 int n; 56 Line A; 57 while(~scanf("%d",&n) && n) 58 { 59 for(int i = 0;i < n;i++) 60 { 61 scanf("%lf %lf",&up[i].x, &up[i].y); 62 down[i].x = up[i].x, down[i].y = up[i].y - 1; 63 } 64 bool flag = false; 65 double ans = -100000000.0; 66 for(int i = 0;i < n;i++) 67 { 68 for(int j = 0;j < n;j++) 69 { 70 int k; 71 A = Line(up[i], down[j]); 72 for(k = 0;k < n;k++){ 73 if(!A.linecrossing(Line(up[k], down[k])) ) 74 { 75 break; 76 } 77 } 78 if(k >= n){flag = true;break;} 79 if(k > max(i, j)) 80 { 81 if(A.linecrossing(Line(up[k], up[k-1]))) 82 { 83 Point x = A.crosspoint(Line(up[k], up[k-1])); 84 ans = max(ans,x.x); 85 } 86 if(A.linecrossing(Line(down[k], down[k-1]))) 87 { 88 Point x = A.crosspoint(Line(down[k], down[k-1])); 89 ans = max(ans,x.x); 90 } 91 } 92 if(flag) break; 93 } 94 } 95 if(flag) printf("Through all the pipe.\n"); 96 else printf("%.2f\n",ans + eps); 97 } 98 return 0; 99 }
POJ 3449 Geometric Shapes
POJ 1584 A Round Peg in a Ground Hole