【NOIP2001】Car的旅行线路
题目描述:点击此处
解题思路:
平行四边形相对顶点的横坐标、纵坐标之和分别相等。
将所有机场的坐标都算出来之后,再根据题目描述连边,从出发地的四个机场或到达地的四个机场分别做单源点最短路。
实现代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<climits>
using namespace std;
#define MAXS 100
int n,s,t,a,b,x[MAXS*4+10],y[MAXS*4+10];
double dist[MAXS*4],ans;
queue<int>q;
bool vis[MAXS*4+10];
struct node{
int v;
double wt;
node *next;
}edge[MAXS*MAXS*4*4+10],*adj[MAXS*4+10],*ecnt;
double straight_dist(int x1,int y1,int x2,int y2){
int t1=x1-x2,t2=y1-y2;
return sqrt(t1*t1+t2*t2);
}
void addedge(int u,int v,double wt){
node *p=++ecnt;
p->v=v;
p->wt=wt;
p->next=adj[u];
adj[u]=p;
}
void find_four(int i){
double a,b,c;
int t1,t2,rp;
a=straight_dist(x[i*4-1],y[i*4-1],x[i*4-2],y[i*4-2]);
b=straight_dist(x[i*4-1],y[i*4-1],x[i*4-3],y[i*4-3]);
c=straight_dist(x[i*4-3],y[i*4-3],x[i*4-2],y[i*4-2]);
if(a>b&&a>c)
rp=3,t1=1,t2=2;
else if(b>a&&b>c)
rp=2,t1=1,t2=3;
else
rp=1,t1=2,t2=3;
x[i*4]=x[i*4-t1]+x[i*4-t2]-x[i*4-rp];
y[i*4]=y[i*4-t1]+y[i*4-t2]-y[i*4-rp];
}
void read_prepare(){
int i,j,k;
double wt;
scanf("%d%d%d%d",&s,&t,&a,&b);
for(i=1;i<=s;i++){
for(j=3;j;j--)
scanf("%d%d",&x[i*4-j],&y[i*4-j]);
double ti;
find_four(i);
scanf("%lf",&ti);
for(j=0;j<=3;j++)
for(k=j+1;k<=3;k++){
wt=straight_dist(x[i*4-j],y[i*4-j],x[i*4-k],y[i*4-k])*ti;
addedge(i*4-j,i*4-k,wt);
addedge(i*4-k,i*4-j,wt);
}
}
for(i=1;i<=s*4;i++)
for(j=1;j<=s*4;j++){
if((i+3)/4==(j+3)/4)
continue;
wt=straight_dist(x[i],y[i],x[j],y[j])*t;
addedge(i,j,wt);
addedge(j,i,wt);
}
}
void spfa(int st){
vis[st]=1;
q.push(st);
for(int i=1;i<=s*4;i++)
dist[i]=INT_MAX/2;
dist[st]=0;
while(!q.empty()){
int u=q.front(),v;
double wt;
q.pop();
vis[u]=0;
for(node *p=adj[u];p;p=p->next){
v=p->v,wt=p->wt;
if(dist[u]+wt<dist[v]){
dist[v]=dist[u]+wt;
vis[v]=1;
q.push(v);
}
}
}
}
int main()
{
scanf("%d",&n);
while(n--){
memset(adj,0,sizeof adj);
ecnt=&edge[0];
read_prepare();
int i,j;
ans=INT_MAX;
for(i=0;i<=3;i++){
spfa(a*4-i);
for(j=0;j<=3;j++)
if(dist[b*4-j]<ans)
ans=dist[b*4-j];
}
printf("%.2lf\n",ans);
}
}