Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 6231 | Accepted: 2499 |
Description
Input
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
Source
Mid-Central USA 1996
本题难点在于建图,枚举所有方向向右的连线并去掉被阻隔的,然后任意一种最短路。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const double INF=10000000.0; int u[10000],v[10000]; double g[100][100],py[20][6],wx[20],dis[100],w[10000]; struct node { double x,y; node(double xx=0,double yy=0) { x=xx,y=yy; } }p[100]; int n,m,vcnt,ecnt; double dist(node a,node b) { return sqrt(1.0*(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double cross(double x1,double y1,double x2,double y2,double x3,double y3) { return (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1); } bool is_ok(node a,node b) { if(a.x>=b.x)return 0; int i=0; while(wx[i]<=a.x&&i<n) i++; while(wx[i]<b.x&&i<n) { if(cross(a.x,a.y,b.x,b.y,wx[i],0)*cross(a.x,a.y,b.x,b.y,wx[i],py[i][0])<0 ||cross(a.x,a.y,b.x,b.y,wx[i],py[i][1])*cross(a.x,a.y,b.x,b.y,wx[i],py[i][2])<0 ||cross(a.x,a.y,b.x,b.y,wx[i],py[i][3])*cross(a.x,a.y,b.x,b.y,wx[i],10)<0) return 0; i++; } return 1; } double bellman() { int i,j,k; for(i=1;i<vcnt;i++)dis[i]=INF; dis[0]=0; for(i=1;i<=vcnt;i++) for(j=0;j<ecnt;j++) if(dis[v[j]]>dis[u[j]]+w[j])dis[v[j]]=dis[u[j]]+w[j]; return dis[vcnt-1]; } int main() { while(~scanf("%d",&n)&&n!=-1) { int i,j;double k; vcnt=0; p[vcnt++]=node(0,5); for(i=0;i<n;i++) { scanf("%lf",&wx[i]);//wx存储墙的横坐标 for(j=0;j<4;j++) { scanf("%lf",&k); p[vcnt++]=node(wx[i],k); py[i][j]=k;//第i面墙(从0数)第j个点 } } p[vcnt++]=node(10,5);//存点完成,开始存边 ecnt=0; for(i=0;i<vcnt;i++) for(j=0;j<vcnt;j++) g[i][j]=INF; for(i=0;i<vcnt;i++) for(j=i+1;j<vcnt;j++) if(is_ok(p[i],p[j]))//去掉被截断的 { u[ecnt]=i; v[ecnt]=j; g[i][j]=dist(p[i],p[j]); w[ecnt++]=g[i][j]; } printf("%.2f\n",(float)bellman());//double的我wa了,网上据说是double的精度问题 } return 0; }