zoj 1891 - 传说中的简答题 - 最短路径 - dijkstra

在复习资料中找到的对应不同类型的题目。想先从简单的题目入手,结果一上来就发现不对劲。感觉有点不简单呀。

之前也是碰到这种问题会畏首畏尾,因为,要计算两点之间的距离的。想着要不要先全部计算出来,放到数组里面分别调用。

但后来又想到不行,这样的时间复杂度更高了,n*(n+1)/2 的时间复杂度。就有点麻乱了。

通过参考网上其他的解答,发现他们也是一边算,一边找的。相比这就是简答题的优势吧。

然后题目的要求是求出最小花费的时间,这几天刚好在复习dijkstra算法。就可以用上了。

这里稍微总结一下:

算法总路线:   以出发点作为最短路径的集合flag,不断的寻找剩余点里面的最短路径,一个一个加入到最短路径集合flag中,并且更新出发点到各个点的最小距离dis。

1、初始化出发点到各个点的最小距离数组dis。这里直接根据各个节点map来计算。

2、总共n个结点,进行n次大循环,依次加入当前状态下最小的结点。

2.1、 通过n次贪心算法,寻找当前状态离出发点的最短距离点;

2.2、标记最短距离点,加入最短路径的集合flag;

2.3、以找到的结点为中介,更新最短路径集合flag。    即比较出  sta-->j    &  sta-->pos-->j  这两种方式哪个最短。

上链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=891

/*
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=891
1、对输入的节点分别录入,并根据线路标记分类;
2、利用dijkstra求出最少花费路径。

	确实是要分别计算两个点之间的距离的。
	dijkstra。循环计算从出发节点到其他节点的最短距离。 

*/

#include <stdio.h>
#include <math.h>

#define M 202
#define INF 0x3f3f3f3f
typedef struct
{
	double x,y;
}NODE;

NODE point[M];
int flag[M];
int cate[M];//在一条线上
double dis[M];

//fl == 1 ,walk; 2,subway
double calc(NODE a, NODE b,int fl)//  sqrt( a*a+b*b )
{
	double tmp1 = (a.x-b.x)*(a.x-b.x);
	double tmp2 = (a.y-b.y)*(a.y-b.y);
	if( fl == 1)
		return sqrt(tmp1+tmp2)/10000*60.0;
	return sqrt(tmp1+tmp2)/40000*60.0;
}

//应该多注意的一点,用来添加最短路径的点循环中,i的作用就是计数,
//用不着它在循环中做判断
void dijkstra(int sta,int n)
{
	int i,j;
	for(i=0 ;i< n; i++)
	{
		flag[i] = 0;
	}
	for(i=1 ; i<n ;i++)
	{
		dis[i] = calc( point[sta], point[i], 1);
	}
	flag[sta] = 1;
	for(i=1 ; i<n ;i++)//循环一次加入每一个点
	{
		double min = INF;
		int pos;
		for(j=1 ; j<n ; j++)//n-1次贪心
		{
			if( flag[j] == 1)continue;
			if( dis[j] < min )
			{
				min = dis[j];
				pos = j;
			}
		}
		flag[pos] = 1;
		dis[pos] = min;

		for(j=1 ; j<n; j++)
		{
			if( flag[j] == 1) continue;
			double t1 = dis[pos];//pos -- j ,'s distance
			if(  cate[pos] == cate[j] && ( pos==j-1 || j==pos-1) )//  中介比较的点是pos,不是i。这里注意
				t1 += calc(point[pos],point[j],2);					//相邻而且在 一条subway上的使用subway方法
			else t1 += calc(point[pos],point[j],1);
			if( t1 < dis[j] )
				dis[j] = t1;
		}

	}
}

int main()
{
	int i,j;
	double x,y;
	while(scanf("%lf%lf", &x, &y) != EOF)
	{
		if( x==-1 && y==-1) break;
		point[0].x= x;
		point[0].y= y;
		scanf("%lf%lf",&point[1].x, &point[1].y);
		cate[0] = 0;//这个时候假设起点、终点与任何一个地铁线路的站台都不在一起
		cate[1] = 1;
		i=2;
		j=2;
		while( scanf("%lf%lf", &x, &y) && (x!=-1) && (y!=-1))
		{
			cate[i] = j;
			point[i].x = x;
			point[i++].y = y;
			while( scanf("%lf%lf", &x, &y) && (x!=-1) && y!=-1)
			{
				cate[i] = j;
				point[i].x = x;
				point[i++].y= y;
			}
			j++;
		}
		/*

		for(j=0 ; j<i ;j++)
			printf("[%d,%d],", point[j].x, point[j].y);*/

		dijkstra(0,i);
		printf("%.0lf\n", dis[1]);
	}

	return 0;
}

一次就AC了之后还是很激动的说。

zoj 1891 - 传说中的简答题 - 最短路径 - dijkstra

时间: 2024-11-09 03:18:54

zoj 1891 - 传说中的简答题 - 最短路径 - dijkstra的相关文章

S2T40.(深入.Net平台和C#编程)第四章.简答题4.刁汉生.20170406

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 简答题.Entity 8 { 9 /// <summary> 10 /// 蚂蚁类 11 /// </summary> 12 public class Ant 13 { 14 //蚂蚁名字 15 publi

S2T40.(深入.Net平台和C#编程)第四章.简答题5.刁汉生.20170406

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 简答题5.Entity 8 { 9 /// <summary> 10 /// 巫师类 11 /// </summary> 12 public class Wizard 13 { 14 /// <sum

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹

数据结构:单源最短路径--Dijkstra算法

Dijkstra算法 单源最短路径 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. Dijkstra算法 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合.假设V0是源点,则初始 S={V

他答对一半(打一字)asp.net开源简答题项目

先出个字谜: 他答对一半(打一字) 你猜出来了没? 可以到这个网址答题:http://hovertree.com/shortanswer/bjae/f53e663164227906.htm 看你的答案是否正确. 这是ASP.NET开源CMS项目HoverTree的一个功能:简答题,目前正在测试中,如果你希望这部分的源代码公布的话,请推荐一下本文,给我开发整理代码的动力,谢谢. HoverTree使用的语言是C#,数据库为Sql Server,基于.NET 4.0,使用三层结构,如果你有兴趣的话,

S2T40.(深入.Net平台和C#编程)第四章.简答题4、5.何强.20170406

简答题4: 简答题5

第四章,简答题4-5,2017-4-6

巫师属性类------- 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 第四章_简答题5.entity 8 { 9 public class Wus 10 { 11 public int SM { get; set; }//生命 12 public int Do {

软工期中测试简答题

软工-期中测试简答题 软件危机的具体表现? 1)成本难以估计.成本高. 2)软件开发进度估计不准确,项目延期比比皆是. 3)软件质量得不到保证(功能和性能). 4)用户对"已完成的"软件系统不满意的现象经常发生. 5)维护非常困难(多样性 .复杂性. 副作用). 6)软件通常没有适当的文档. 7)软件产品供不应求,跟不上计算机普及速度. 产生软件危机的原因? (1)软件日益复杂和庞大 (2)软件开发管理困难和复杂 (3)软件开发技术落后 (4)生产方式落后 (5)开发工具落后 (6)软

hdu1818 It&#39;s not a Bug, It&#39;s a Feature!(隐式图最短路径Dijkstra)

题目链接:点击打开链接 题目描述:补丁在修bug时,有时也会引入新的bug,假设有n(n<=20)个潜在的bug和m(m<=100)个补丁,每个补丁用两个长度为n的字符串表示,其中字符串的每个位置表示一个bug.第一个串表示打补丁之前的状态('-'表示在该位置不存在bug,'+'表示该位置必须存在bug,0表示无所谓),第二个串表示打补丁之后的状态('-'表示不存在,'+'表示存在,0表示不变).每个补丁都有一个执行时间,你的任务是用最少的时间把一个所有bug都存在的软件通过打补丁的方式变得没