在复习资料中找到的对应不同类型的题目。想先从简单的题目入手,结果一上来就发现不对劲。感觉有点不简单呀。
之前也是碰到这种问题会畏首畏尾,因为,要计算两点之间的距离的。想着要不要先全部计算出来,放到数组里面分别调用。
但后来又想到不行,这样的时间复杂度更高了,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了之后还是很激动的说。