hdoj 1548(迪杰斯塔拉-最短路径)

迪杰斯特拉算法主要是,在图中找两个点(源点到其他顶点)之间的最短路径。一步一步的求出两点之间的最短路径,过程中是基于上一次已经求出的最短路径的基础上,来去求得更远顶点的最短路径,最终得到你要的结果。

//代码来源《大话数据结构》,有增删。

/*  Dijkstra算法,求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度D[v] */    
/*  P[v]的值为前驱顶点下标,D[v]表示v0到v的最短路径长度和 */  
#define MAXVEX 20
#define INFINITY 65535
void Dijkstra(MGraph G, int v0, Patharc *P, ShortPathTable *D)
{    
	int v,w,k,min;    
	int final[MAXVEX];		   /* final[w]=1表示求得顶点v0至vw的最短路径 */
	for(v=0; v<G.numVertexes; v++)     /* 初始化数据 */
	{        
		final[v] = 0;			/* 全部顶点初始化为未知最短路径状态 */
		(*D)[v] = G.arc[v0][v];       /* 将与v0点有连线的顶点加上权值 */
		(*P)[v] = 0;				/* 初始化路径数组P为0  */       
	}

	(*D)[v0] = 0;     /* v0至v0路径为0 */  
	final[v0] = 1;    /* v0至v0不需要求路径 */        
	/* 开始主循环,每次求得v0到某个v顶点的最短路径 */   
	for(v=1; v<G.numVertexes; v++)   
	{
		min=INFINITY;    /* 当前所知离v0顶点的最近距离 */        
		for(w=0; w<G.numVertexes; w++) /* 寻找离源点最近的顶点 */    
		{            
			if(!final[w] && (*D)[w]<min)             
			{                   
				k=w;                    
				min = (*D)[w];               
			}        
		}        
		final[k] = 1;    /* 将目前找到的最近的顶点置为1 */
	  /* 修正当前最短路径及距离 */	
		for(w=0; w<G.numVertexes; w++) 
       
		{
			/* 如果经过v顶点的路径比现在这条路径的长度短的话 */
			if(!final[w] && (min+G.arc[k][w]<(*D)[w]))         //这里为什么用k作为比较的下一个行。因为,上个for循环。找到了本节点与下一个点的最短路径的连接点就是k ,再去找与k这一行有最短路径的点(k与其他顶点。)。 

			{ /*  说明找到了更短的路径, 修改当前路径长度 */
			 
				(*D)[w] = min + G.arc[k][w];  /* min是上一个顶点到本顶点的最短距离,加上本节点到与本节点有边且没有访问过的点(即w点)的最小距离,组成源点到w的最短距离,存放再D数组里面 */              
				(*P)[w]=k;        
			}       
		}   
	}
}

用最短路径去解决。

Hdoj --1548

思路:转化为两点之间是否可达,再转化为用迪杰斯特拉算法求最短路径就行了。

#include<stdio.h>
#include<string.h>
#define inf 0x3fffffff
int map[205][205];

int dijks(int s,int t,int n)
{
    bool visit[205];
    int dis[205];
    int i,j,k,min;
    memset(visit,false,sizeof(visit));
    visit[s]=true;
    for(i=1;i<=n;++i)
        dis[i]=map[s][i];
    for(i=1;i<n;++i)
    {
        min=inf;
        k=1;
        for(j=1;j<=n;++j)
        {
            if(!visit[j]&&min>dis[j])  
            {
                min=dis[j];
                k=j;
            }
        }
        if(k==t||min==inf)
            break;
        visit[k]=true;
        for(j=1;j<=n;++j)
        {
            if(!visit[j]&&dis[k]+map[k][j]<dis[j])
                dis[j]=dis[k]+map[k][j];
        }
    }
    if(dis[t]==inf)
        return -1;
    else
        return dis[t];
}

int main()
{
    int n,a,b,i,j;
    int button[205];
    while(scanf("%d",&n),n)
    {
        scanf("%d%d",&a,&b);
        for(i=1;i<=n;++i)
            scanf("%d",&button[i]);
        if(a==b)   
        {
            printf("0\n");
            continue;
        }
        if(a>n||b>n)
        {
            printf("-1\n");
            continue;
        }
        for(i=1;i<=n;++i)
            for(j=1;j<i;++j)
                map[i][j]=map[j][i]=inf;
        for(i=1;i<=n;++i) 	//初始化图,只要想到这一步,问题基本就解决了。
        {
            if(i+button[i]<=n)
                map[i][i+button[i]]=1;
            if(i-button[i]>0)
                map[i][i-button[i]]=1;
        }
        

        printf("%d\n",dijks(a,b,n));
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值