21476: Car的旅行路线
时间限制: 1 Sec 内存限制: 128 MB
提交: 2 解决: 1
[提交][状态][讨论版][命题人:外部导入]
题目描述
又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个城市都有四个飞机场,分别位于一个矩形的四个顶点上,同一个城市中两个机场之间有一 条笔直的高速铁路,第I个城市中高速铁路了的单位里程价格为Ti,任意两个不同城市的机场之间均有航线,所有航线单位里程的价格均为t。
那么Car应如何安排到城市B的路线才能尽可能的节省花费呢?她发现这并不是一个简单的问题,于是她来向你请教。
找出一条从城市A到B的旅游路线,出发和到达城市中的机场可以任意选取,要求总的花费最少。
输入
第一行有四个正整数s,t,A,B。
S表示城市的个数,t表示飞机单位里程的价格,A,B分别为城市A,B的序号,(1<=A,B<=S)。
接下来有S行,其中第I行均有7个正整数xi1,yi1,xi2,yi2,xi3,yi3,Ti,这当中的(xi1,yi1),(xi2,yi2),(xi3,yi3)分别是第I个城市中任意三个机场的坐标,T I为第I个城市高速铁路单位里程的价格。
数据规模和约定
0
输出
共有n行,每行一个数据对应测试数据,保留一位小数。
样例输入
3 10 1 3
1 1 1 3 3 1 30
2 5 7 4 5 2 1
8 6 8 8 11 6 3
样例输出
47.5
对于s个城市,每个城市4个机场,视为4*s个结点,这4*s个节点构成了一个图,转变为求最短路径问题,采用Dijkstra方法。边存储每个城市的机场信息,边计算各机场间距离和费用并存入邻接表中。整体思路不复杂,但实现起来很麻烦,很容易出错,比如在存储的格式、计算距离、存储邻接表等细节上。
代码
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXV = 405;
const double INF = 100000000.0;
int s, t, A, B;
struct node{ //用于存储机场坐标,方便计算距离
int x, y;
};
struct airport{ //对s个城市,每个城市的机场布局存于该结构体中。s内有四个元素
vector<node> s;
int T;
};
struct NODE{ //用于存在邻接表的结构体
int v;
double dis;
};
vector<NODE> Adj[MAXV]; //邻接表
vector<airport> airp; //存储s个城市的机场信息
double d[MAXV]; //最短距离
bool vis[MAXV] = {false};
node findLastPoint(node s1, node s2, node s3){ //给出矩形的三个顶点坐标,求第四个顶点坐标
if((s2.x - s1.x) * (s3.x- s1.x) + (s2.y - s1.y) * (s3.y- s1.y) == 0){
node tmp;
tmp.x = s2.x + s3.x - s1.x;
tmp.y = s2.y + s3.y - s1.y;
return tmp;
}else if((s1.x - s2.x) * (s3.x- s2.x) + (s1.y - s2.y) * (s3.y- s2.y) == 0){
node tmp;
tmp.x = s1.x + s3.x - s2.x;
tmp.y = s1.y + s3.y - s2.y;
return tmp;
}else{
node tmp;
tmp.x = s1.x + s2.x - s3.x;
tmp.y = s1.y + s2.y - s3.y;
return tmp;
}
}
double D(node s1, node s2){ //求两坐标s1和s2的距离
double d = sqrt((s1.x - s2.x) * (s1.x - s2.x) + (s1.y - s2.y) * (s1.y - s2.y));
return d;
}
double MIN(double a, double b, double c, double d) { //四个距离中的最小值
double tmp;
if(a < b){
tmp = a;
}else{
tmp = b;
}
if(c < tmp){
tmp = c;
}
if(d < tmp){
tmp = d;
}
return tmp;
}
void Dijkstra(int a){
fill(d, d + MAXV, INF);
fill(vis, vis + MAXV, false);
d[a] = 0.0;
for(int i = 0; i < s*4; i++) {
int u = -1;
double MIN = INF;
for(int j = 0; j < s*4; j++) {
if(vis[j] == false && d[j] < MIN) {
u = j;
MIN = d[j];
}
}
if(u == -1) return;
vis[u] = true;
for(int j = 0; j < Adj[u].size(); j++) {
int v = Adj[u][j].v;
if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]){
d[v] = d[u] + Adj[u][j].dis;
}
}
}
}
int main() {
scanf("%d %d %d %d", &s, &t, &A, &B);
for(int i = 0; i < s; i++) {
//首先读入第i个城市机场信息并存储在airp中
airport tmpA;
for(int j = 0; j < 3; j++) {
node tmpN;
scanf("%d %d", &tmpN.x, &tmpN.y);
tmpA.s.push_back(tmpN); //将三个结点存入
}
tmpA.s.push_back(findLastPoint(tmpA.s[0], tmpA.s[1], tmpA.s[2])); //存入第四个结点
scanf("%d", &tmpA.T);
airp.push_back(tmpA);
//下面是存储邻接表
//本城市内部
for(int j = 0; j < 4; j++) { //该城市四个机场每两个机场之间距离和开销
for(int k = 0; k < 4; k++){
if(j != k) {
NODE tmp;
tmp.v = i*4 + k;
tmp.dis = D(tmpA.s[j], tmpA.s[k]) * tmpA.T;
Adj[i*4 + j].push_back(tmp);
}
}
}
//不同城市间
for(int j = 0; j < 4; j++) { //对本城市四个机场 j
for(int k = 0; k < i; k++) { //对前面每个城市k
for(int l = 0; l < 4; l++) { //对目标城市的四个机场l
NODE tmp;
tmp.v = k*4 + l;
tmp.dis = D(tmpA.s[j], airp[k].s[l]) * t;;
Adj[i*4 + j].push_back(tmp);
tmp.v = i*4 + j;//双向邻接表
Adj[k*4 + l].push_back(tmp);
}
}
}
}
//计算以出发城市的四个机场为起点和以目标城市的四个机场为终点的16个最短距离,取其最小值
double dis[4];
for(int i = 0; i < 4; i++) {
Dijkstra((A - 1)*4 + i);
dis[i] = MIN(d[(B - 1)*4], d[(B - 1)*4 + 1], d[(B - 1)*4 + 2], d[(B - 1)*4 + 3] );
}
printf("%.1f\n", MIN(dis[0], dis[1], dis[2], dis[3]));
return 0;
}