依次放置 n 根木棍(線段),後放的在上層。若木棍與已放置的任意木棍相交或接觸,則該木棍「不在最上層」。求最終處於最上層的木棍編號(按放置順序輸出)。
struct Point { double x, y; };
Point operator-(Point A, Point B) { return {A.x-B.x, A.y-B.y}; }
double Cross(Point A, Point B) { return A.x*B.y - A.y*B.x; }
double Dot(Point A, Point B) { return A.x*B.x + A.y*B.y; }
// 嚴格相交(內部交點)
bool SegInter(Point a1, Point a2, Point b1, Point b2) {
double c1 = Cross(a2-a1, b1-a1);
double c2 = Cross(a2-a1, b2-a1);
double c3 = Cross(b2-b1, a1-b1);
double c4 = Cross(b2-b1, a2-b1);
return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
}
// 點在線段上(含端點)
bool OnSegment(Point P, Point A, Point B) {
return dcmp(Cross(A-P, B-P)) == 0 && dcmp(Dot(P-A, P-B)) <= 0;
}
stick[1..n]i(1~n),檢查是否與任意 j > i 相交/接觸i 為最上層木棍,加入結果Top sticks: a, b, c.)#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
const double EPS = 1e-10;
int dcmp(double x) { return fabs(x)0?1:-1); }
struct Point { double x, y; };
struct Stick { Point a, b; };
Point operator-(Point A, Point B) { return {A.x-B.x, A.y-B.y}; }
double Cross(Point A, Point B) { return A.x*B.y - A.y*B.x; }
double Dot(Point A, Point B) { return A.x*B.x + A.y*B.y; }
bool SegInter(Point a1, Point a2, Point b1, Point b2) {
double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1);
double c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);
return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}
bool OnSegment(Point P, Point A, Point B) {
return dcmp(Cross(A-P, B-P))==0 && dcmp(Dot(P-A, P-B))<=0;
}
int main() {
int n;
while (scanf("%d", &n) == 1 && n) {
vector s(n+1);
for (int i = 1; i <= n; i++)
scanf("%lf%lf%lf%lf", &s[i].a.x, &s[i].a.y, &s[i].b.x, &s[i].b.y);
vector top;
for (int i = 1; i <= n; i++) {
bool covered = false;
for (int j = i+1; j <= n; j++) {
if (SegInter(s[i].a, s[i].b, s[j].a, s[j].b) ||
OnSegment(s[i].a, s[j].a, s[j].b) ||
OnSegment(s[i].b, s[j].a, s[j].b)) {
covered = true; break;
}
}
if (!covered) top.push_back(i);
}
printf("Top sticks: ");
for (int i = 0; i < top.size(); i++) {
if (i) printf(", ");
printf("%d", top[i]);
}
printf(".\n");
}
return 0;
}
O(n²),n ≤ 1000 可接受(約 50 萬次檢查)O(n log n),但本題不必要EPS=1e-10,所有比較用 dcmpn=0 結束