多邊形頂點按**逆時針 (或順時針)** 順序給定。對於任意三個連續頂點 P[i], P[i+1], P[i+2] (索引取模),構建向量:
v1 = P[i+1] - P[i]v2 = P[i+2] - P[i+1]計算**叉積 (Cross Product)** cross = v1.x * v2.y - v1.y * v2.x:
cross > 0:左轉 (逆時針凸角)cross < 0:右轉 (凹角)cross == 0:共線若**所有叉積同號 (全 ≥ 0 或全 ≤ 0)**,則為凸多邊形;否則為凹多邊形。
import java.util.Scanner;
public class ConvexPolygonJudge {
static class Point {
int x, y;
Point() {}
Point(int x, int y) { this.x = x; this.y = y; }
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (true) {
int n = sc.nextInt();
if (n == 0) break;
Point[] p = new Point[n];
for (int i = 0; i < n; i++) {
int x = sc.nextInt();
int y = sc.nextInt();
p[i] = new Point(x, y);
}
boolean convex = true;
for (int i = 0; i < n; i++) {
int j = i;
int k = (i + 1) % n;
int t = (i + 2) % n;
// 向量 v1 = P[k] - P[j], v2 = P[t] - P[k]
int v1x = p[k].x - p[j].x;
int v1y = p[k].y - p[j].y;
int v2x = p[t].x - p[k].x;
int v2y = p[t].y - p[k].y;
int cross = v1x * v2y - v1y * v2x;
if (cross < 0) { // 逆時針序列應全為非負
convex = false;
break;
}
}
System.out.println(convex ? "convex" : "concave");
}
sc.close();
}
}
| 細節 | 處理方式 |
|---|---|
| 索引循環 | 取模 (i+1)%n、(i+2)%n 處理首尾相接 |
| 頂點順序 | 題目給定逆時針,故要求 cross >= 0;若順時針則要求 cross <= 0 |
| 共線邊界 | cross == 0 視為凸 (允許 180° 角),嚴格凸需 > 0 |
| 整數溢位 | 座標範圍較大時用 long 儲存叉積 |
| 最小頂點數 | n < 3 直接視為非多邊形 (題目通常保證 n ≥ 3) |
本文原始內容亦包含三角形中心計算,補充整理如下:
(O-A + O-B)·(A-B) = 0 等 → 解線性方程組I = (a*A + b*B + c*C) / (a+b+c) (a,b,c 為對邊長)r = 2S / (a+b+c) (S 為面積,海倫公式)G = (A + B + C) / 3H = A + B + C - 2O (O 為外心)凸多邊形判定是計算幾何入門必修課。**向量叉積** 不僅能判定凸凹,更是「點在多邊形內」、「線段相交」、「凸包構建」等核心問題的基石。掌握整數座標下的叉積運算與取模索引技巧,即可輕鬆應對 ACM/ICPC 類幾何題。