2011-08-31 23:12:34Morris
c107. Jack Straws
c107. Jack Straws
內容 :
在一張桌子上倒一些吸管,給你這些吸管2端點的座標,請你寫一個程式來回答某2根吸管是否有相連。相連是指2根吸管有直接接觸或經由其他吸管可以連接。
輸入說明 :
輸入的第一列有一個正整數,代表以下有幾組測試資料。第一列與第一組測試資料,以及各組測試資料間均有一空白列。請參考Sample Input。
每組測試資料的第一列有1個正整數n(1 < n < 13),代表吸管的數目。接下來的n列依序代表第1根吸管到第n根吸管,每列有4個正整數x1, y1, x2, y2,代表這根吸管2端點的座標(x1, y1),( x2, y2)。所有的座標值均小於100,且吸管的長度一定大於0。再接下來的數列為此組測試資料的子問題,每列有2個正整數a,b(均介於1到n之間),你必須回答第a根吸管和第b根吸管有無相連。當a=b=0時代表此組測試資料結束。
輸出說明 :
對每一組測試資料,回答其各子問題。若相連請輸出CONNECTED,否則請輸出NOT CONNECTED
各組測試資料間請輸出一空白列。請參考Sample Output。
範例輸入 :
271 6 3 3 4 6 4 9 4 5 6 7 1 4 3 5 3 5 5 5 5 2 6 3 5 4 7 2 1 4 1 6 3 3 6 7 2 3 1 3 0 021 1 1 31 7 1 51 21 10 0
範例輸出 :
CONNECTEDNOT CONNECTEDCONNECTEDCONNECTEDNOT CONNECTEDCONNECTEDNOT CONNECTEDCONNECTED
提示 :
* Luck 貓翻譯
出處 :
ACM 273 (管理:sa072686)
作法 : 數學
對於相交的兩個線段 :
1. 拿一個線段的一端點, 往外拉三條向量, 分別是拉到自己的另外一個端點,
拉到另外一個線段的兩端點, 這兩個向量分別與自己拉出來的向量外積, 這兩個外積值相乘會小於 0,
外積正負可以看出順時針或者是逆時針, 對於 4 個端點都要符合
2. 或者是有某點在另外一個線段上
作法 : 數學
對於相交的兩個線段 :
1. 拿一個線段的一端點, 往外拉三條向量, 分別是拉到自己的另外一個端點,
拉到另外一個線段的兩端點, 這兩個向量分別與自己拉出來的向量外積, 這兩個外積值相乘會小於 0,
外積正負可以看出順時針或者是逆時針, 對於 4 個端點都要符合
2. 或者是有某點在另外一個線段上
/**********************************************************************************/
/* Problem: c107 "Jack Straws" from ACM 273 */
/* Language: C */
/* Result: AC (0ms, 194KB) on ZeroJudge */
/* Author: morris1028 at 2011-08-31 23:02:26 */
/**********************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxV 1000000
typedef struct {
int x, y;
}Point;
typedef struct {
Point s, e;
}Segment;
Segment D[14];
int Map[14][14];
int Min(int x, int y) {
return x < y ? x : y;
}
int Max(int x, int y) {
return x > y ? x : y;
}
int Cross(Point s, Point t1, Point t2, Point e) {
Point T1, T2, M;
M.x = e.x-s.x, M.y = e.y-s.y;
T1.x = t1.x-s.x, T1.y = t1.y-s.y;
T2.x = t2.x-s.x, T2.y = t2.y-s.y;
return (M.x*T1.y - M.y*T1.x)*(M.x*T2.y - M.y*T2.x) < 0 ? 1 : 0;
}
int Collinear(Point x, Point y, Point z) {/*x-y-z (O) y-x-Z(X)*/
int miny = x.y, maxy = x.y;
miny = Min(x.y, z.y);
maxy = Max(x.y, z.y);
if((x.x-y.x)*(z.y-y.y) == (x.y-y.y)*(z.x-y.x) && (x.x <= y.x && z.x >= y.x) &&
(miny <= y.y && maxy >= y.y))
return 1;
return 0;
}
int JudgeIntersect(Segment A, Segment B) {
if(Cross(A.s, B.s, B.e, A.e) && Cross(A.e, B.s, B.e, A.s) &&
Cross(B.s, A.s, A.e, B.e) && Cross(B.e, A.s, A.e, B.s))
return 1;
if(Collinear(A.s, B.s, A.e) || Collinear(A.s, B.e, A.e) ||
Collinear(B.s, A.s, B.e) || Collinear(B.s, A.e, B.e) )
return 1;
return 0;
}
void Handle(int n) {
int i, j;
memset(Map, 0, sizeof(Map));
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
if(JudgeIntersect(D[i], D[j]))
Map[i][j] = 1;
}
}
}
void Floyd(int n) {
int i, j, k;
for(i = 0; i < n; ++i)
for(j = 0; j < n; ++j)
if(Map[i][j] == 0)
Map[i][j] = MaxV;
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
for(k = 0; k < n; k++)
if(Map[j][i] + Map[i][k] < Map[j][k])
Map[j][k] = Map[j][i] + Map[i][k];
}
main() {
int n, i, j, k, x, y;
Point T;
scanf("%d", &k);
while(k--) {
scanf("%d", &n);
for(i = 0; i < n; i++) {
scanf("%d %d %d %d", &D[i].s.x, &D[i].s.y, &D[i].e.x, &D[i].e.y);
if(D[i].s.x > D[i].e.x) {
T = D[i].s, D[i].s = D[i].e, D[i].e = T;
}
}
Handle(n), Floyd(n);
while(scanf("%d %d", &x, &y) == 2) {
if(x == 0 && y == 0) break;
x--, y--;
if(Map[x][y] == MaxV)
puts("NOT CONNECTED");
else
puts("CONNECTED");
}
if(k) puts("");
}
return 0;
}