URAL 1205 By the Underground or by Foot (建图 + Dijkstra + 堆优化)

#include <stdio.h>
#include <math.h>
#define INF (1 << 30)

double footSpeed, undergroundSpeed;
int numOfStations;
int start, end;
typedef struct Coordinates{
	double x;
	double y;
}Cooridnates;
Coordinates CoordinatesArray[300];
double timeArray[300][300];
double minTimeArray[300];
int stack[300];
int top;
int pre[300];
int heapSize;
typedef struct Node{
	double minTime;
	int location;
}Node;
Node heap[300];

double getDistance(Coordinates one, Coordinates another){
	double deltaX = one.x - another.x;
	double deltaY = one.y - another.y;
	return sqrt(deltaX * deltaX + deltaY * deltaY);
}

void swap(Node *a, Node *b){
	Node c = *a;
	*a = *b;
	*b = c;
}

void heapDecreaseKey(int NodeIndex,double minTime){
	heap[NodeIndex].minTime = minTime;
	while (NodeIndex > 1 && heap[NodeIndex].minTime < heap[ NodeIndex >> 1 ].minTime){
		swap(&heap[NodeIndex], &heap[ NodeIndex >> 1 ]);
		NodeIndex = NodeIndex >> 1;
	}
}

void minHeapify(int parent){
	int least = parent;
	int left = parent << 1;
	if (left <= heapSize && heap[left].minTime < heap[least].minTime)
		least = left;
	int right = (parent << 1) + 1;
	if (right <= heapSize && heap[right].minTime < heap[least].minTime)
		least = right;
	if (least != parent){
		swap(&heap[parent], &heap[least]);
		minHeapify(least);
	}
}

void buildMinHeap(){
	int to;
	for (to = heapSize >> 1; to >= 1; to--)
		minHeapify(to);
}

double getMinTimeByDijkstra(){
	heapSize = 0;
	int to;
	for (to = 1; to <= end; to++){
		if (to != start){
			heapSize++;
			heap[heapSize].minTime = timeArray[start][to];
			heap[heapSize].location = to;	
		}
	}

	buildMinHeap();

	int numOfMinTimesFound;
	for (numOfMinTimesFound = 2; numOfMinTimesFound <= end; numOfMinTimesFound){
		double minTime = heap[1].minTime;
		int location = heap[1].location;
		if (location == end)
			return minTime;
		swap(&heap[1], &heap[heapSize]);
		heapSize--;
		int NodeIndex;
		for (NodeIndex = 1; NodeIndex <= heapSize; NodeIndex++){
			Node tempNode = heap[NodeIndex];
			if (minTime + timeArray[location][tempNode.location] < tempNode.minTime){
				heapDecreaseKey(NodeIndex, minTime + timeArray[location][tempNode.location]);
				pre[tempNode.location] = location;
			}
		}	
		minHeapify(1);
	}
		
}

int main(){

	scanf("%lf%lf", &footSpeed, &undergroundSpeed);

	scanf("%d", &numOfStations);
	int station;
	for (station = 1; station <= numOfStations; station++){
		Coordinates tempCoordinates;
		scanf("%lf%lf", &tempCoordinates.x, &tempCoordinates.y);
		CoordinatesArray[station] = tempCoordinates;
	}

	int from, to;
	for (from = 1; from <= numOfStations; from++)
		for (to = from + 1; to <= numOfStations; to++)
			//注意:默认可以从一个车站步行到另一个车站
			timeArray[from][to] = timeArray[to][from] = getDistance(CoordinatesArray[from], CoordinatesArray[to]) / footSpeed;

	while (scanf("%d%d", &from, &to) != EOF && (from != 0 && to != 0) )
		timeArray[from][to] = timeArray[to][from] = getDistance(CoordinatesArray[from], CoordinatesArray[to]) / undergroundSpeed;
	
	start = numOfStations + 1;
	end = numOfStations + 2;
	scanf("%lf%lf", &CoordinatesArray[start].x, &CoordinatesArray[start].y);
	scanf("%lf%lf", &CoordinatesArray[end].x, &CoordinatesArray[end].y);
	int location;
	for (location = 1; location <= end; location++){
		timeArray[start][location] = timeArray[location][start] = getDistance(CoordinatesArray[start], CoordinatesArray[location]) / footSpeed;
		timeArray[end][location] = timeArray[location][end] = getDistance(CoordinatesArray[end], CoordinatesArray[location]) / footSpeed;
	}

	//注意输出精度
	printf("%.10lf\n", getMinTimeByDijkstra());

	int preLocation = pre[end];
	while (preLocation != 0){
		stack[++top] = preLocation;
		preLocation = pre[preLocation];
	}

	printf("%d", top);
	while (top > 0)
		printf(" %d", stack[top--]);
	printf("\n");

	return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值