洛谷 P1907 设计道路

题目描述

Caesar远征高卢回来后,对你大加赞赏,他亲自来到Genoa视察。

Genoa在你的建设下变得无比繁荣,由于财政收入的增加,你为城市修建了交通系统。古罗马的交通系统由两部分组成——Dirt Road和Rome Road。两个路口间只可能是其中一种道路。在Rome Road上可以驾驶马车,而在Dirt Road上则不行。由于修建道路是一项浩大的工程,使得你无法将整个城市用Rome Road连接起来。

现在Caesar已经到达码头,他要求去你家参观。Caesar由一个癖好,喜欢坐车而不喜欢走路。所以Caesar走Dirt Road时的不满值要比走Rome Road时大。

为了不让Caesar过于不满而罢免你的职位,请设计路线使得Caesar的不满值最小。

输入格式

输入数据第一行有两个实数,分别表示走Dirt Road和Rome Road一个单位长度时Caesar的不满值。接下来是一个整数N(N<=1000),代表路口总数。接下来有N行,每行一组实数(x,y)分别描述这N个路口的坐标。接下来有若干行,每行一组整数(i,j),表示第i个路口与第j个路口间为Rome Road,以0 0结束。最后两行,每行一对实数,分别描述码头和你家的坐标。

输出格式

输出Caesar从码头到你家的最小不满值,保留4位小数

输入输出样例

输入 #1

100.0 2.0
2
1.0 0.0
2.0 1.0
1 2
0 0
0.0 0.0
2.0 2.0

输出 #1

202.8284
#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
const int MAXN = 1004; 
const int INF = 100000000;

double graph[MAXN][MAXN];  //邻接矩阵存图 
double dis[MAXN];
bool vis[MAXN];
double cx[MAXN];  //cx[i]存放i号路口的x坐标 
double cy[MAXN];  //cx[i]存放i号路口的y坐标

void Dijkstra(int s,int n){
	fill(dis,dis+n+2,INF);
	dis[s] = 0;
	for(int i=0;i<=n+1;i++){
		int u = -1;
		int minDis = INF;
		for(int j=0;j<=n+1;j++){
			if(!vis[j] && dis[j] < minDis){
				minDis = dis[j];
				u = j;
			}
		}
		if(u == n+1){
			break;
		}
		vis[u] = true;
		for(int j=0;j<=n+1;j++){
			double w = graph[u][j];
			if(!vis[j]){
				if(dis[j] > dis[u] + w){
					dis[j] = dis[u] + w;
				}
			}
		}
	}
} 

int main(){
	double dirt,rome; //dirt路的不满度和rome路的不满度 
	int n;  //路口个数 
	double x,y,sx,sy,tx,ty,height,width; //坐标 
	int u,v;  //边的起点和终点 
	double w; //边的权重 
	cin>>dirt>>rome;
	cin>>n;
	//输入每个路口的坐标 
	for(int i=1;i<=n;i++){
		cin>>cx[i]>>cy[i];
	}
	//输入路口u与路口v之间的Rome Road边 
	while(cin>>u>>v){
		if(u==0 && v==0){break;}
		height = cy[u] - cy[v];  //垂直长度
		width = cx[u] - cx[v];   //水平长度 
		//计算边的权重
		w = sqrt(height*height + width*width) * rome;
		graph[u][v] = graph[v][u] = w; 
	}
	cin>>cx[0]>>cy[0]>>cx[n+1]>>cy[n+1]; 
	
	/*
	** 任意两点之间用dirt路连接上
	** 如果i和j之间本来没有路,那就直接用dirt road
	** 如果i和j之间本来有rome raod,那就比较一下dirt road和rome road的不满度,
	** 选小的那个 
	*/
	for(int i=0;i<=n+1;i++){
		for(int j=i+1;j<=n+1;j++){
			height = cy[i] - cy[j];
			width = cx[i] - cx[j];
			w = sqrt(height*height + width*width) * dirt;
			if(graph[i][j] == 0 || graph[i][j] > w){
				graph[i][j] = graph[j][i] = w;
			}
		}
	} 
	Dijkstra(0,n);
	cout<<fixed<<setprecision(4)<<dis[n+1]<<endl;
	return 0;
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值