标签:alt names input 定义 main rom put 思路 nal
题目链接:
http://poj.org/problem?id=1066
题目描述:
Description
Input
Output
Sample Input
7 20 0 37 100 40 0 76 100 85 0 0 75 100 90 0 90 0 71 100 61 0 14 100 38 100 47 47 100 54.5 55.4
Sample Output
Number of doors = 2
题目大意:
给定一些在 (0,0) 和 (100,100) 之间的线段,在房间的墙的中点可以开门,问最少开多少门,可以从边上到达目标点
思路:
枚举边上的整点(但不能是给出的线段的端点)和整点之间带0.5的点作为起点,与目标点连成线段,与多少线段相交即需要开多少门,因为若与这些线段相交,则一定要在这些线段的某个墙的中点开门,两者等价
代码:
1 #include <cmath> 2 #include <algorithm> 3 #include <cstdio> 4 #include <iostream> 5 #include <cstring> 6 using namespace std; 7 8 const double EPS = 1e-10; //精度系数 9 const int N = 32; 10 const int M = 101; 11 const int INF = 0x3f3f3f3f; 12 13 struct Point { 14 double x, y; 15 Point(double x = 0, double y = 0) :x(x), y(y) {} 16 }; //点的定义 17 18 typedef Point Vector; //向量的定义 19 20 Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); } //向量减法 21 22 int dcmp(double x) { 23 if (fabs(x) < EPS)return 0; else return x < 0 ? -1 : 1; 24 } //与0的关系 25 26 double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; } //向量叉乘 27 28 bool SegmentProperIntersection(Point& a1, Point& a2, Point& b1, Point& b2) { 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 34 Point A[N], B[N], T; 35 bool edge[M][M]; 36 37 int main() { 38 int n, a1, b1, a2, b2, ans = INF; 39 cin >> n; 40 for (int i = 0; i < n; ++i) { 41 scanf("%d%d%d%d", &a1, &b1, &a2, &b2); 42 edge[a1][b1] = edge[a2][b2] = true; //边界上有线段顶点 43 A[i].x = a1, A[i].y = b1, B[i].x = a2, B[i].y = b2; 44 } 45 scanf("%lf%lf", &T.x, &T.y); 46 for (int i = 0; i < 100; ++i) { //底边 47 if (i && !edge[i][0]) { 48 int cnt = 0; 49 Point p(i, 0); 50 for (int j = 0; j < n; ++j) 51 if (SegmentProperIntersection(T, p, A[j], B[j]))++cnt; 52 ans = min(cnt, ans); 53 } 54 int cnt = 0; 55 Point p(i + 0.5, 0); 56 for (int j = 0; j < n; ++j) 57 if (SegmentProperIntersection(T, p, A[j], B[j]))++cnt; 58 ans = min(cnt, ans); 59 } 60 for (int i = 0; i < 100; ++i) { //上边 61 if (i && !edge[i][100]) { 62 int cnt = 0; 63 Point p(i, 100); 64 for (int j = 0; j < n; ++j) 65 if (SegmentProperIntersection(T, p, A[j], B[j]))++cnt; 66 ans = min(cnt, ans); 67 } 68 int cnt = 0; 69 Point p(i + 0.5, 100); 70 for (int j = 0; j < n; ++j) 71 if (SegmentProperIntersection(T, p, A[j], B[j]))++cnt; 72 ans = min(cnt, ans); 73 } 74 for (int i = 0; i < 100; ++i) { //左侧边 75 if (i && !edge[0][i]) { 76 int cnt = 0; 77 Point p(0, i); 78 for (int j = 0; j < n; ++j) 79 if (SegmentProperIntersection(T, p, A[j], B[j]))++cnt; 80 ans = min(cnt, ans); 81 } 82 int cnt = 0; 83 Point p(0, i + 0.5); 84 for (int j = 0; j < n; ++j) 85 if (SegmentProperIntersection(T, p, A[j], B[j]))++cnt; 86 ans = min(cnt, ans); 87 } 88 for (int i = 0; i < 100; ++i) { //右侧边 89 if (i && !edge[100][i]) { 90 int cnt = 0; 91 Point p(100, i); 92 for (int j = 0; j < n; ++j) 93 if (SegmentProperIntersection(T, p, A[j], B[j]))++cnt; 94 ans = min(cnt, ans); 95 } 96 int cnt = 0; 97 Point p(100, i + 0.5); 98 for (int j = 0; j < n; ++j) 99 if (SegmentProperIntersection(T, p, A[j], B[j]))++cnt; 100 ans = min(cnt, ans); 101 } 102 printf("Number of doors = %d\n", ans + 1); //加上最外层边的那个 1 103 }
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 6995 | Accepted: 2895 |
Description
Input
Output
Sample Input
7 20 0 37 100 40 0 76 100 85 0 0 75 100 90 0 90 0 71 100 61 0 14 100 38 100 47 47 100 54.5 55.4
Sample Output
Number of doors = 2
标签:alt names input 定义 main rom put 思路 nal
原文地址:http://www.cnblogs.com/hyp1231/p/7010723.html