Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 2942 | Accepted: 1331 |
Description
Input
Output
Sample Input
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 Output
CONNECTED NOT CONNECTED CONNECTED CONNECTED NOT CONNECTED CONNECTED CONNECTED CONNECTED CONNECTED
Source
给出二维平面上的一些线段,之后有一些询问,判断各对线段是否是连通的
由于线段数比较少,可以先判断一遍每对线段之间是否是直接相连的,之后再用Floyd算法找出两条线段之间是否可以间接相连,最后对每组询问,可以直接O(1)给出答案
判断两条线段是否有交点可以先求出两条线段所在直线的交点,之后再判断交点是否在两条线段上。
在几何问题中,运用向量的内积和外积进行计算是非常方便的。对于二维向量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之间。
此题中还要注意边界情况,数据中可能存在两条线段在同一条直线上(即它们是平行的,或者说是共线的),但它们可能在端点处有公共点,这里我们要通过检查端点是否在另一条线段上来判断
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 }
POJ 1127 Jack Straws,布布扣,bubuko.com
原文:http://www.cnblogs.com/lzj-0218/p/3574380.html