【P1027 [NOIP2001 提高组] Car 的旅行路线】
思路:
单源最短路问题,首先输入数据只给了每个城市的三个点的坐标,第四个点的坐标必须自己思考,但是这四个点的相对几何位置不固定,因此需要用迭代法不断交换三个点的位置:A-B-C --> B-C-A --> C-A-B......直到三个点的位置如图所示,这样就可以求出第四个点的坐标了,然后再用数组构造一个图,同一城市机场间的边的长度=机场间的距离该城市铁路单价,不同城市的机场间的边长=机场间的距离飞机票单价,再用最短路算法求解,最佳算法是dijkstra。
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cmath>
#include <algorithm>
#define INF 10000000
#define CTOA(x) (((x-1)<<2)+1)
#define DISTANCE(x1,y1,x2,y2) ((double)sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)))
using namespace std;
double node[4050][4050];
double T;
int tx[3],ty[3],t;
double ans=INF;
struct city
{
int x[4];
int y[4];
}ct[105];
void getfour(int c)
{
int tt;
memcpy(tx,ct[c].x,sizeof(tx));
memcpy(ty,ct[c].y,sizeof(ty));
while((tx[0]-tx[1])*(tx[2]-tx[1])+(ty[0]-ty[1])*(ty[2]-ty[1]))
{
tt=tx[0]; tx[0]=tx[1]; tx[1]=tx[2]; tx[2]=tt;
tt=ty[0]; ty[0]=ty[1]; ty[1]=ty[2]; ty[2]=tt;
}
ct[c].x[3]=tx[0]-tx[1]+tx[2];
ct[c].y[3]=ty[0]-ty[1]+ty[2];
}
int min(int a1,int b1)
{
if(a1<b1) return a1;
return b1;
}
int main()
{
int i,j,k,l,m,n;
scanf("%d",&n);
while(n--)
{
int s,t,a,b;
cin>>s>>t>>a>>b;
if(a==b) { cout<<"0.0\n"; continue;}
int airport=s<<2;
for(i=1;i<=airport;i++)
{
for(j=1;j<=airport;j++)
node[i][j]=INF;
}
for(i=1;i<=s;i++)
{
for(j=0;j<3;j++)
cin>>ct[i].x[j]>>ct[i].y[j];
cin>>T;
getfour(i);
for(j=0;j<4;j++)
{
for(k=0;k<4;k++)
if(j!=k)
node[CTOA(i)+j][CTOA(i)+k]=(DISTANCE(ct[i].x[j],ct[i].y[j],ct[i].x[k],ct[i].y[k])*T);
}
}
for(i=1;i<=s;i++)
{
for(j=1;j<=s;j++)
{
if(i!=j)
for(k=0;k<4;k++)
{
for(l=0;l<4;l++)
node[CTOA(i)+k][CTOA(j)+l]=(DISTANCE(ct[i].x[k],ct[i].y[k],ct[j].x[l],ct[j].y[l])*t);
}
}
}
//Floyd
for(k=1;k<=airport;k++)
{
for(i=1;i<=airport;i++)
{
for(j=1;j<=airport;j++)
{
node[i][j]=min(node[i][j],node[i][k]+node[k][j]);
}
}
}
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
ans=min(ans,node[CTOA(a)+i][CTOA(b)+j]);
}
cout<<setiosflags(ios::fixed)<<setprecision(1)<<ans<<endl;
}
return 0;
}