http://acm.nyist.net/JudgeOnline/problem.php?pid=83php
題目解法主要在於判斷兩線段是否相交,思路是窮舉全部地圖四周的點,其中每個邊界上的點和終點構成一個線段, 求出全部線段和牆相交的最少次數就是結果.net
#include<stdio.h> struct point { double x, y; }; struct line { point a, b; }; double det(double x1, double y1, double x2, double y2)//計算叉積 { return x1 * y2 - x2 * y1; } double get_dir(point a, point b, point c)//計算向量ac 在向量ab的哪一個方向(正數爲逆時針,負數爲順時針, 零爲同向或者反向) { return det(b.x - a.x, b.y - a.y, c.x - a.x, c.y - a.y); } int check_cross(line a, line b)//計算出兩條線段是否相交,注意只有肯定兩條線段的都在對方的兩側,才能肯定這兩條線段相交 { double flag1 = get_dir(a.a, a.b, b.a) * get_dir(a.a, a.b, b.b); int f1 = flag1 > 0 ? 1 : -1; double flag2 = get_dir(b.a, b.b, a.a) * get_dir(b.a, b.b, a.b); int f2 = flag2 > 0? 1 : -1; if(f1 < 0 && f2 < 0) return -1; else return 1; } line lines[40]; int axis1[101], axis2[101], axis3[101], axis4[101]; int get_cross_number(point start, point end, int total)//計算相交次數 { line templine; templine.a = start; templine.b = end; int count = 0; int i; for(i = 0; i < total; i++) { if(check_cross(templine, lines[i]) - 0 < 1e-6) count ++; } return count; } int main() { int n; scanf("%d", &n); while(n--) { int m; int top1, top2, top3, top4; top1 = top2 = top3 = top4 = 0; scanf("%d", &m); int i; for(i = 0; i < m; i++) { int x1, x2, y1, y2; scanf("%d %d %d %d", &x1, &y1, &x2, &y2); lines[i].a.x = x1; lines[i].a.y = y1; lines[i].b.x = x2; lines[i].b.y = y2; } point end; scanf("%lf %lf", &end.x, &end.y); int min = 0x7fffffff; for(i = 0; i < 101; i++) { if(min == 0) break; point start; int res; start.x = 0; start.y = i; res = get_cross_number(start, end, m); if(res < min) min = res; start.x = 100; start.y = i; res = get_cross_number(start, end, m); if(res < min) min = res; start.x = i; start.y = 0; res = get_cross_number(start, end, m); if(res < min) min = res; start.x = i; start.y = 100; res = get_cross_number(start, end, m); if(res < min) min = res; } printf("%d\n", min + 1); } return 0; }