계산 기하학 + 검색 집합 처리: POJ 1127 Jack Straws
n 개의 작은 막대기 가 2 차원 평면 에 분포 되 어 있 고 모든 작은 막대기 가 양쪽 의 좌 표를 표시 했다. 작은 막대기 의 번 호 는 1 ~ n 이다. 현재 의 문 제 는 두 개의 작은 막대기 의 번 호 를 제시 하여 연결 되 어 있 는 지 물 어 보 는 것 이다.
여기 서 연 결 된 정 의 는 직접 연결 하거나 여러 개의 다른 작은 막대 기 를 통 해 간접 적 으로 연결 할 수 있다 는 것 이다.
두 개의 작은 막대기 의 교차 상황 (예 를 들 어 그들의 교점 좌 표를 직접 구 하 는 것) 을 직접 연구 할 수 없고 벡터 를 고려 할 수 있다.
벡터 에서 벡터 P1 = S1 - T1, P2 = S2 - T2 (모든 변 수 는 벡터) 를 가정 하면 교차 여 부 를 고려 하 는 것 은 (평행 을 고려 하지 않 는 것) 과 같다.
1) 두 벡터 가 대표 하 는 직선 교차점 이 Q 라 고 가정 하고 이때 Q 에 대응 하 는 벡터 가 Q 라 고 가정 하면 벡터 P1 과 Q 의 관 계 는 Q = T1 + (S1 - T1) * a (a 는 하나의 계수) 이다.
2) 벡터 P2 에 대해 차 승의 각도 에서: (S2 - T2) X (Q - T2) = 0;
3) 상기 두 방정식 을 연결 하면 a = (T2 - S2) X (T1 - T2) / [(S2 - T2) X (S1 - T1)] 를 구 할 수 있 고 Q 의 좌표 도 나온다.
4) Q 가 P1 과 P2 를 대표 하 는 선분 위 에 있 는 지, 아니면 벡터 를 사용 하 는 지 를 토론 합 니 다. 이때 Q 가 선분 안에 있 으 면 (두 개의 점 포함) 다음 과 같 습 니 다. (Q - S1) * (Q - T1) < = 0 & & (Q - S2) * (Q - T2) < = 0;
다음은 평행 상황 을 토론 한다.
만약 에 두 개의 벡터 가 평행 하 는 동시에 이들 이 서로 포함 되 는 지 (즉, 겹 치 는 일부분 이 있 는 지) 를 토론 하려 면 사실은 특정한 선분 의 특정한 점 이 다른 선분 안에 있 는 지 논증 하 는 것 이다. 그래서 네 가지 상황 이 있 을 것 이다. 여기 서 논술 을 생략 하 는 것 이다.
이런 처 리 를 한 후에 바로 연 결 된 나무 막대 기 를 알 게 되 었 다. 그 다음 에 간접 적 으로 연 결 된 나무 막대 기 는 사실은 폐쇄 문 제 를 전달 하 는 것 이 므 로 Warshall 알고리즘 을 사용 하거나 집합 을 찾 을 수 있다.
1. 기 하 + Warshall 계산, 복잡 도 O (N ^ 3) 712 K / 79MS 수락
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int maxn = 15;
const double EPS = 1e-10;
int n;
bool grap[maxn][maxn];
//
double add(double a, double b) {
if (abs(a + b) < EPS*(abs(a) + abs(b))) return 0;
return a + b;
}
struct Point {
double x, y;
Point(){};
Point(double x, double y): x(x), y(y){}
Point operator + (Point p) {
return Point(add(x, p.x), add(y, p.y));
}
Point operator - (Point p) {
return Point(add(x, -p.x), add(y, -p.y));
}
Point operator * (double p) {
return Point(x*p, y*p);
}
//
double dot(Point p) {
return add(x*p.x, y*p.y);
}
//
double det(Point p) {
return add(x*p.y, -y*p.x);
}
};
Point s[maxn], t[maxn];
// q st
bool on_seg(Point& s, Point& t, Point& q) {
return (s - q).det(t - q) == 0 && (q - s).dot(q - t) <= 0;
}
//
Point intersection(Point& s1, Point& t1, Point& s2, Point& t2) {
return t1 + (s1 - t1)*((t2 - s2).det(t1 - t2) / (s2 - t2).det(s1 - t1));
}
void init() {
for (int i = 1; i <= n; i++) {
grap[i][i] = true;
for (int j = 1; j < i; j++) {
if ((s[i] - t[i]).det(s[j] - t[j]) == 0) {
grap[i][j] = grap[j][i] = on_seg(s[i], t[i], s[j]) || on_seg(s[i], t[i], t[j]) || on_seg(s[j], t[j], s[i]) || on_seg(s[j], t[j], t[i]);
}
else {
Point temp = intersection(s[i], t[i], s[j], t[j]);
grap[i][j] = grap[j][i] = on_seg(s[i], t[i], temp) && on_seg(s[j], t[j], temp);
}
}
}
//Warshall Algorithm
for (int k = 1; k <= n; k++) {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
grap[i][j] |= grap[i][k] && grap[k][j];
}
}
}
}
int main() {
int a, b;
while (scanf("%d", &n) && n != 0) {
for (int i = 1; i <= n; i++) scanf("%lf %lf %lf %lf", &s[i].x, &s[i].y, &t[i].x, &t[i].y);
init();
while (scanf("%d %d", &a, &b) && a*b != 0) printf(grap[a][b] ? "CONNECTED
" : "NOT CONNECTED
");
}
return 0;
}
2. 기 하 + 를 계산 하고 집합 을 찾 습 니 다: O (N ^ 2) + O (log (N)) Accept 721 K / 47MS
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn = 15;
const double EPS = 1e-10;
int n;
int flag[maxn];//
int Rank[maxn];//
bool grap[maxn][maxn];
double add(double a, double b) {
if (abs(a + b) < EPS*(abs(a) + abs(b))) return 0;
return a + b;
}
struct Point {
double x, y;
Point(){};
Point(double x, double y): x(x), y(y){}
Point operator + (Point p) {
return Point(add(x, p.x), add(y, p.y));
}
Point operator - (Point p) {
return Point(add(x, -p.x), add(y, -p.y));
}
Point operator * (double p) {
return Point(x*p, y*p);
}
double dot(Point p) {
return add(x*p.x, y*p.y);
}
double det(Point p) {
return add(x*p.y, -y*p.x);
}
};
Point s[maxn], t[maxn];
bool on_seg(Point& s, Point& t, Point& q) {
return (s - q).det(t - q) == 0 && (q - s).dot(q - t) <= 0;
}
Point intersection(Point& s1, Point& t1, Point& s2, Point& t2) {
return t1 + (s1 - t1)*((t2 - s2).det(t1 - t2) / (s2 - t2).det(s1 - t1));
}
//
int findRoot(int x) {
if (flag[x] == x) return x;
return flag[x] = findRoot(flag[x]);
}
// ( )
void unite(int x, int y) {
x = findRoot(x);
y = findRoot(y);
if (x == y) return;
if (Rank[x] < Rank[y]) flag[x] = flag[y];
else {
flag[y] = flag[x];
if (Rank[x] == Rank[y]) Rank[x]++;
}
}
void init() {
for (int i = 1; i <= n; i++) flag[i] = i;
for (int i = 1; i <= n; i++) {
grap[i][i] = true;
for (int j = 1; j < i; j++) {
if ((s[i] - t[i]).det(s[j] - t[j]) == 0) {
grap[i][j] = grap[j][i] = on_seg(s[i], t[i], s[j]) || on_seg(s[i], t[i], t[j]) || on_seg(s[j], t[j], s[i]) || on_seg(s[j], t[j], t[i]);
}
else {
Point temp = intersection(s[i], t[i], s[j], t[j]);
grap[i][j] = grap[j][i] = on_seg(s[i], t[i], temp) && on_seg(s[j], t[j], temp);
}
if (grap[i][j]) unite(i, j);
}
}
}
int main() {
int a, b;
memset(Rank, 0, sizeof(Rank));
while (scanf("%d", &n) && n != 0) {
for (int i = 1; i <= n; i++) scanf("%lf %lf %lf %lf", &s[i].x, &s[i].y, &t[i].x, &t[i].y);
init();
while (scanf("%d %d", &a, &b) && a*b != 0) printf(findRoot(a) == findRoot(b) ? "CONNECTED
" : "NOT CONNECTED
");
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
물체 검출의 평가 지표 IoU의 계산 방법Yolo나 SSD 등 물체 검출에서 평가 지표로 사용되는 IoU에 대해 조사했으므로 정리했습니다. IoU (Intersection over Union)는 두 영역이 얼마나 겹치는지를 나타내는 지표입니다. 두 영역의 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.