POJ 1127 Jack Straws

Jack Straws
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 2942   Accepted: 1331

Descriptionios

In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are connected by a path of touching straws. You will be given a list of the endpoints for some straws (as if they were dumped on a large piece of graph paper) and then will be asked if various pairs of straws are connected. Note that touching is connecting, but also two straws can be connected indirectly via other connected straws.

Input算法

Input consist multiple case,each case consists of multiple lines. The first line will be an integer n (1 < n < 13) giving the number of straws on the table. Each of the next n lines contain 4 positive integers,x1,y1,x2 and y2, giving the coordinates, (x1,y1),(x2,y2) of the endpoints of a single straw. All coordinates will be less than 100. (Note that the straws will be of varying lengths.) The first straw entered will be known as straw #1, the second as straw #2, and so on. The remaining lines of the current case(except for the final line) will each contain two positive integers, a and b, both between 1 and n, inclusive. You are to determine if straw a can be connected to straw b. When a = 0 = b, the current case is terminated. 

When n=0,the input is terminated. 

There will be no illegal input and there are no zero-length straws. 

Outputless

You should generate a line of output for each line containing a pair a and b, except the final line where a = 0 = b. The line should say simply "CONNECTED", if straw a is connected to straw b, or "NOT CONNECTED", if straw a is not connected to straw b. For our purposes, a straw is considered connected to itself.

Sample Inputide

7
1 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 0

2
0 2 0 0
0 0 0 1
1 1
2 2
1 2
0 0

0

Sample Outputspa

CONNECTED 
NOT CONNECTED 
CONNECTED 
CONNECTED 
NOT CONNECTED 
CONNECTED
CONNECTED
CONNECTED
CONNECTED

Sourcecode

 

給出二維平面上的一些線段,以後有一些詢問,判斷各對線段是不是連通的blog

因爲線段數比較少,能夠先判斷一遍每對線段之間是不是直接相連的,以後再用Floyd算法找出兩條線段之間是否能夠間接相連,最後對每組詢問,能夠直接O(1)給出答案ip

判斷兩條線段是否有交點能夠先求出兩條線段所在直線的交點,以後再判斷交點是否在兩條線段上。rem

在幾何問題中,運用向量的內積和外積進行計算是很是方便的。對於二維向量p1=(x1,y1)和p2=(x2,y2),咱們定義內積p1·p2=x1*x2+y1*y2,外積p1×p2=x1*y2-y1*x2。要判斷點q是否在線段p1-p2上,只要先用外積跟據是否有(p1-q)×(p2-q)=0來判斷點q是否在直線p1-p2上,再利用內積根據是否有(p1-q)·(p2-q)≤0來判斷點q是否落在p1-p2之間。get

此題中還要注意邊界狀況,數據中可能存在兩條線段在同一條直線上(即它們是平行的,或者說是共線的),但它們可能在端點處有公共點,這裏咱們要經過檢查端點是否在另外一條線段上來判斷

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cmath>
  5 #define MAX_N 15
  6 
  7 using namespace std;
  8 
  9 double EPS=1e-10;
 10 
 11 double add(double a,double b)
 12 {
 13     if(fabs(a+b)<EPS*(fabs(a)+fabs(b)))
 14         return 0;
 15     return a+b;
 16 }
 17 
 18 struct P
 19 {
 20     double x,y;
 21 
 22     P(){}
 23 
 24     P(double x,double y):x(x),y(y){}
 25 
 26     P operator + (P p)
 27     {
 28         return P(add(x,p.x),add(y,p.y));
 29     }
 30 
 31     P operator - (P p)
 32     {
 33         return P(add(x,-p.x),add(y,-p.y));
 34     }
 35 
 36     P operator * (double d)
 37     {
 38         return P(x*d,y*d);
 39     }
 40 
 41     //內積
 42     double dot(P p)
 43     {
 44         return add(x*p.x,y*p.y);
 45     }
 46 
 47     //外積
 48     double det(P p)
 49     {
 50         return add(x*p.y,-y*p.x);
 51     }
 52 };
 53 
 54 //判斷點q是否在線段p1-p2上
 55 bool on_seg(P p1,P p2,P q)
 56 {
 57     return (p1-q).det(p2-q)==0&&(p1-q).dot(p2-q)<=0;
 58 }
 59 
 60 //計算直線p1-p2與直線q1-q2的交點
 61 P intersection(P p1,P p2,P q1,P q2)
 62 {
 63     return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
 64 }
 65 
 66 int n;
 67 P p[MAX_N],q[MAX_N];
 68 bool g[MAX_N][MAX_N];
 69 
 70 void solve()
 71 {
 72     for(int i=0;i<n;i++)
 73     {
 74         g[i][i]=true;
 75         for(int j=0;j<i;j++)
 76         {
 77             //判斷木棍i和木棍j是否有公共點
 78             if((p[i]-q[i]).det(p[j]-q[j])==0)
 79             {
 80                 //平行時,判斷是否可能在端點處有交點
 81                 g[i][j]=g[j][i]=on_seg(p[i],q[i],p[j])||on_seg(p[i],q[i],q[j])||on_seg(p[j],q[j],p[i])||on_seg(p[j],q[j],q[i]);
 82             }
 83             else
 84             {
 85                 //非平行時,先求出兩直線交點再湊數交點是否在兩條線段上
 86                 P r=intersection(p[i],q[i],p[j],q[j]);
 87                 g[i][j]=g[j][i]=on_seg(p[i],q[i],r)&&on_seg(p[j],q[j],r);
 88             }
 89         }
 90     }
 91 
 92     //經過Floyd-Warshall算法判斷任意的兩點間是否相連
 93     for(int k=0;k<n;k++)
 94         for(int i=0;i<n;i++)
 95             for(int j=0;j<n;j++)
 96                 g[i][j]|=g[i][k]&&g[k][j];
 97 }
 98 
 99 int main()
100 {
101     while(scanf("%d",&n)&&n)
102     {
103         for(int i=0;i<n;i++)
104             scanf("%lf %lf %lf %lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y);
105         solve();
106         int a,b;
107         while(scanf("%d %d",&a,&b)&&(a||b))
108             puts(g[a-1][b-1]?"CONNECTED":"NOT CONNECTED");
109     }
110 
111     return 0;
112 }
[C++]
相關文章
相關標籤/搜索