Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 7641 | Accepted: 2987 |
Description
Input
2
4 2 7 8 9
7 3 4.5 6 7
The first line contains the number of interior walls. Then there is a line for each such wall, containing five real numbers. The first number is the x coordinate of the wall (0 < x < 10), and the remaining four are the y coordinates of the ends of the doorways in that wall. The x coordinates of the walls are in increasing order, and within each line the y coordinates are in increasing order. The input file will contain at least one such set of data. The end of the data comes when the number of walls is -1.
Output
Sample Input
1 5 4 6 7 8 2 4 2 7 8 9 7 3 4.5 6 7 -1
Sample Output
10.00 10.06
不错的一个题.
题意:求(0,5)和(10,5)两个点之间的最短距离
先把每个点和每条线段记录下来,然后每两个点之间如果能够直连就根据下标记录下来距离(这里要判断两个点连成的线段是否与其之间的所有线段有交点,有交点就不能直连,我用了两个变量对自身线段做了特判)然后用最短路算法进行求解。三层循环0MS,这题数据也是水。
#include <iostream> #include <cstdio> #include <string.h> #include <math.h> #include <algorithm> using namespace std; struct Point{ double x,y; }p[400]; struct Line{ Point a,b; }line[400]; int n; const double INF = 9999999; double mp[400][400]; double low[400]; bool vis[400]; double dijstra(int n){ memset(vis,false,sizeof(vis)); memset(low,0,sizeof(low)); int pos = 0; vis[pos]=true; for(int i=0;i<=n;i++){ low[i] = mp[pos][i]; } for(int i=0;i<n-1;i++){ int mi = INF; for(int j=0;j<=n;j++){ if(!vis[j]&&mi>low[j]){ pos = j; mi = low[j]; } } vis[pos] = true; for(int j=0;j<=n;j++){ if(!vis[j]&&mp[pos][j]+low[pos]<low[j]){ low[j] = mp[pos][j]+low[pos]; } } } return low[n]; } double dis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } ///叉积 double mult(Point a, Point b, Point c) { return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y); } ///a, b为一条线段两端点c, d为另一条线段的两端点 相交返回true, 不相交返回false bool isCross(Point a, Point b, Point c, Point d) { if (max(a.x,b.x)<min(c.x,d.x))return false; if (max(a.y,b.y)<min(c.y,d.y))return false; if (max(c.x,d.x)<min(a.x,b.x))return false; if (max(c.y,d.y)<min(a.y,b.y))return false; if (mult(c, b, a)*mult(b, d, a)<0)return false; if (mult(a, d, c)*mult(d, b, c)<0)return false; return true; } void addline(double x,double y1,double y2,int &k){ line[k].a.x = line[k].b.x =x; line[k].a.y = y1; line[k].b.y = y2; k++; } int main() { while(scanf("%d",&n)!=EOF&&n!=-1){ int k = 0,m=1; ///k代表线段的条数,m代表点的个数 p[0].x = 0,p[0].y = 5; ///起点 for(int i=0;i<n;i++){ double x,y1,y2,y3,y4; scanf("%lf%lf%lf%lf%lf",&x,&y1,&y2,&y3,&y4); p[m].x =x,p[m++].y = y1; p[m].x =x,p[m++].y = y2; p[m].x =x,p[m++].y = y3; p[m].x =x,p[m++].y = y4; addline(x,0,y1,k); addline(x,y2,y3,k); addline(x,y4,10,k); } p[m].x = 10,p[m].y = 5; ///终点 for(int i=0;i<=m;i++){ for(int j=0;j<=m;j++) mp[i][j]=INF; } for(int i=0;i<=m;i++){ for(int j=i+1;j<=m;j++){ Line l; l.a.x = p[i].x,l.a.y = p[i].y; l.b.x = p[j].x,l.b.y = p[j].y; if(l.a.x==l.b.x) continue; int temp,temp1; for(int t=0;t<k;t++){ ///特判 if(line[t].a.x==p[j].x&&line[t].a.y==p[j].y) { temp = t;break; } if(line[t].b.x==p[j].x&&line[t].b.y==p[j].y) { temp = t;break; } } for(int t=0;t<k;t++){ if(line[t].a.x==p[i].x&&line[t].a.y==p[i].y) { temp1 = t;break; } if(line[t].b.x==p[i].x&&line[t].b.y==p[i].y) { temp1 = t;break; } } bool flag = true; for(int t=0;t<k;t++){ if(t==temp||t==temp1) continue; if(isCross(l.a,l.b,line[t].a,line[t].b)){ flag = false; break; } } if(flag){ mp[i][j] = mp[j][i] = dis(p[i],p[j]); } } } double ans = dijstra(m); printf("%.2lf\n",ans); } return 0; }