在复习资料中找到的对应不同类型的题目。想先从简单的题目入手,结果一上来就发现不对劲。感觉有点不简单呀。
之前也是碰到这种问题会畏首畏尾,因为,要计算两点之间的距离的。想着要不要先全部计算出来,放到数组里面分别调用。
但后来又想到不行,这样的时间复杂度更高了,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; }
zoj 1891 - 传说中的简答题 - 最短路径 - dijkstra,布布扣,bubuko.com
zoj 1891 - 传说中的简答题 - 最短路径 - dijkstra
原文地址:http://blog.csdn.net/ls1160/article/details/38117309