180 likes | 406 Views
634 - Polygon. 資科二 99703014 蕭綱玉 99703018 俞光隆 99703047 林孟毅. 前言. 題目簡介. 將 多邊形各個 點 輸入 判斷最後輸入點是否在此多邊形內 最後回傳 T or F. 題目 設定. all edges of the polygon are vertical or horizontal segments lengths of all the edges of the polygon are even integer numbers
E N D
634 - Polygon 資科二 99703014 蕭綱玉 99703018 俞光隆 99703047 林孟毅
題目簡介 • 將多邊形各個點輸入 • 判斷最後輸入點是否在此多邊形內 • 最後回傳T or F
題目設定 • all edges of the polygon are vertical or horizontal segments • lengths of all the edges of the polygon are even integer numbers • co-ordinates of at least one vertex are odd integer numbers • both co-ordinates of any vertex cannot be divisible by 7 at the same time • the investigated point P has both co-ordinates being even integer numbers • the polygon has at most 1000 vertices • co-ordinates of the vertices lay in the range: -10000..10000.
Input and Output • Input Input data may consist of several data sets, each beginning with a number of polygon's vertices (n). Consecutive n lines contain co-ordinates of the vertices (x followed by y). Then go the co-ordinates of investigated point P. Input data end when you find 0 the number of polygon's vertices. • Output For each polygon and each point P you should print one character (in separate lines): T when P belongs to the polygon or F otherwise.
再來我們… scanf("%d %d", &point.x, &point.y); if(inpolygon(point, amount)) printf("T\n"); else printf("F\n"); } return 0; } • 用C檔做出了一個 main 程式 int main() { int n, x, y, i, amount; while(scanf("%d", &n) && n!=0) { for(i = amount = 0; i < 1000; ++i) v[i].x = v[i].y = 0; while(n-- > 0) { scanf("%d %d", &v[amount].x, &v[amount].y); ++amount; }
三種解法 • 叉乘判別法(只適用於凸多邊形) • 面積判別法(只適用於凸多邊形) • 角度和判別法(適用於簡單多邊形)
叉乘判別法 • 比較直覺的方式,是沿著凸多邊形外圍繞一圈,看看點是不是在每一條邊的同側即可。若發現外積皆小於零,即表示點在多邊形內部:若發現外積等於零,即表示點在凸多邊形上、或在凸多邊形某條邊的延伸線上;若發現外積大於零,則表示點在凸多邊形外部。 • 另外一種方式,是將點到凸多邊形頂點的各條向量,利用外積運算判斷是否都往同一方向旋轉,如果都是往同一方向旋轉,則表示點在凸多邊形內部;如果中途出現反方向旋轉,則表示點在凸多邊形外部;如果中途出現外積為零的情況,表示點在凸多邊形上,而且就在對應的邊上。 • 時間複雜度為 O(N) , N 為凸多邊形的頂點數目。 • 只適用於凸多邊形,故不贅述
面積判別法 • 凸多邊形內任選一點作為原點(例如所有點的平均值),然後依角度大小排序凸多邊形的所有頂點。之後就可以用 Binary Search 找出給定的點在哪個夾角之內,最後判斷點是不是在此夾角構成的三角形裡面。 • O(NlogN) 預處理, O(logN) 求答案。 • 只適用於凸多邊形,故不贅述
射線(適用於簡單多邊形) • 原理很簡單,從給定點開始,往隨便一個方向(通常是水平往右)射出一條無限長射線,看看穿過多少條邊,如果穿過偶數次,表示點在簡單多邊形外部;如果穿過奇數次,表示點在簡單多邊形內部。 • 時間複雜度為 O(N) , N 為簡單多邊形的頂點數目。
射線(適用於簡單多邊形) #include<stdio.h> #include<stdlib.h> struct Vertex { int x, y; } v[1000], point; intinpolygon(struct Vertex point, int amount) { intans = -1, i, j; for (i = 0, j = amount-1; i < amount; j = i++) if ((v[i].y > point.y) != (v[j].y > point.y) && point.x < (v[j].x-v[i].x)*(point.y-v[i].y)/(v[j].y-v[i].y)+v[i].x) ans *= -1; return (ans==1); }
完整程式碼 • #include<stdio.h> • #include<stdlib.h> • struct Vertex { • int x, y; • } v[1000], point; • intinpolygon(struct Vertex point, int amount) • { • intans = -1, i, j; • for (i = 0, j = amount-1; i < amount; j = i++) • if ((v[i].y > point.y) != (v[j].y > point.y) && • point.x < (v[j].x-v[i].x)*(point.y-v[i].y)/(v[j].y-v[i].y)+v[i].x) • ans *= -1; • return (ans==1); • } • int main() { • int n, x, y, i, amount; • while(scanf("%d", &n) && n!=0) { • for(i = amount = 0; i < 1000; ++i) • v[i].x = v[i].y = 0; • while(n-- > 0) { • scanf("%d %d", &v[amount].x, &v[amount].y); • ++amount; • } • scanf("%d %d", &point.x, &point.y); • if(inpolygon(point, amount)) • printf("T\n"); • else • printf("F\n"); • } • return 0; • }
Sample Input 4 1 1 1 3 3 3 3 1 2 2 12 1 1 1 9 3 9 3 5 5 5 5 9 7 9 7 1 5 1 5 3 3 3 3 1 4 2 0 • Sample Output T F
時間複雜度 • 首先我們要先完成一個多邊形 • 其複雜度就是 O(n) n表示是n多邊形 • 再來我們利用射線完成其題目要求 • 其複雜度也是 O(n) n也是n多邊形 • O(n) + O(n)= O(n)
THE END Here comes the final exam………..