noip的原题,虽然思维量不大但是挺麻烦的。。。
原题链接:https://www.luogu.org/problemnew/show/P1027
本题的主要问题就是求每个城市第四个点的坐标。其余三点之间的连线中,一定有一条是对角线,所以不参与构成这条边的点,与第四个点的连线就是另一条对角线。平行四边形对角线相互评分,第四个点的坐标就求出来了。
然后就是按题意连边,连边之后做spfa即可,dij想必也可。a城市的每个点取到b城市四个点的最短花费,然后再在a城市的四个点中选一个最小值即可。
另外注意多组数据的清空与精度问题。
#include<cstdio> #include<cmath> #include<queue> #include<cstring> #include<iostream> using namespace std; const int inf=1000000000.0; int t,n,x[505],y[505],cnt; int head[505],gm[505]; void read(int &y) { y=0;char x=getchar(); while(x<'0'||x>'9') x=getchar(); while(x>='0'&&x<='9') { y=y*10+x-'0'; x=getchar(); } } struct edge { int u,v; double w; }e[400005]; void add(int u,int v,double w) { e[++cnt].u=head[u]; e[cnt].v=v; e[cnt].w=w; head[u]=cnt; } double dis[505]; void spfa(int s) { queue<int>q; for(int i=0;i<(n<<2);i++) dis[i]=inf; q.push(s);dis[s]=0; while(!q.empty()) { int t=q.front();q.pop(); for(int i=head[t];i;i=e[i].u) { int tmp=e[i].v; if(dis[tmp]>dis[t]+e[i].w) { dis[tmp]=dis[t]+e[i].w; q.push(tmp); } } } } double cw(int x,int y,int z,int w) { return sqrt((x-z)*(x-z)+(y-w)*(y-w)); } double min(double x,double y,double z,double w) { double re=x; if(y<re) re=y; if(z<re) re=z; if(w<re) re=w; return re; } int main() { read(t); while(t--) { memset(head,0,sizeof(head));cnt=0; int a,b,fm; read(n);read(fm);read(a);read(b); for(int i=0;i<n;i++) { int j=i*4; read(x[j+1]);read(y[j+1]); read(x[j+2]);read(y[j+2]); read(x[j+3]);read(y[j+3]);read(gm[i]); double w1=cw(x[j+1],y[j+1],x[j+2],y[j+2]); double w2=cw(x[j+1],y[j+1],x[j+3],y[j+3]); double w3=cw(x[j+2],y[j+2],x[j+3],y[j+3]); { if(w1>w2&&w1>w3){x[j]=x[j+1]+x[j+2]-x[j+3];y[j]=y[j+1]+y[j+2]-y[j+3];} if(w2>w1&&w2>w3){x[j]=x[j+1]+x[j+3]-x[j+2];y[j]=y[j+1]+y[j+3]-y[j+2];} if(w3>w1&&w3>w2){x[j]=x[j+3]+x[j+2]-x[j+1];y[j]=y[j+3]+y[j+2]-y[j+1];} } } for(int i=0;i<(n<<2);i++) { for(int j=0;j<(n<<2);j++) { if(i==j) continue; double lw=cw(x[i],y[i],x[j],y[j]); if((i>>2)==(j>>2)) add(i,j,gm[i>>2]*lw); else add(i,j,fm*lw); } } a<<=2,b<<=2; double s1,s2,s3,s4; spfa(a-4);s1=min(dis[b-4],dis[b-3],dis[b-2],dis[b-1]); spfa(a-3);s2=min(dis[b-4],dis[b-3],dis[b-2],dis[b-1]); spfa(a-2);s3=min(dis[b-4],dis[b-3],dis[b-2],dis[b-1]); spfa(a-1);s4=min(dis[b-4],dis[b-3],dis[b-2],dis[b-1]); printf("%.1lf ",min(s1,s2,s3,s4)); } return 0; }