hdu 2066 一个人的旅行

18 篇文章 0 订阅
8 篇文章 0 订阅

hdu  2066  一个人的旅行              题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2066

最短路 Dijstra

题目分析:求最短路,用dijstra就能做。此题中稍有拐弯的地方是,起止点都不唯一,找最短,应分别分析起止。起点不唯一(不符单源),可以将各起点存为数组,分别求解找最短,亦可构造单源,另设源点(比如设为0,那么其他点的序号是从1开始的,0到各起点距离都为0,本题即采用此种方法);终点不唯一,可以在构造出distance数组后,循环遍历distance[终点i],找到最短从函数返回。

code:

#include<stdio.h>
#define INF 0x7fffffff
int t,s,d,end[1001],max,map[1001][1001],i,j,k;
int dijstra(int sta)
{
	bool vis[1001];//以为初值0,懒得再初始化了,结果wrong死
	int dis[1001];
	//memset(dis,INF,sizeof(dis));//第一处 
	for(i=0;i<1001;i++)dis[i]=INF,vis[i]=false;//第二处 
	for(i=0;i<max;i++)
	{
		dis[i]=map[sta][i];
	}
	dis[0]=0;
	vis[sta]=true;
	for(i=0;i<max;i++)
	{
		int mark=sta,temp=INF;
		for(j=1;j<=max;j++)
		{
			if(!vis[j]&&sta!=j)
			{
				if(map[sta][j]<INF&&dis[j]>dis[sta]+map[sta][j])
				{
					//printf("现在应该从 %d 到 %d \n",sta,j);
					dis[j]=dis[sta]+map[sta][j];
				}
				if(dis[j]<temp)
				{
					//printf("现在的dis[%d]==%d\n",j,dis[j]);
					temp=dis[j];
					mark=j;
				}
			}
		}
		//if(temp==0||temp==INF)break;第三处 
		vis[mark]=true;
		sta=mark;
	}
	int ans=INF;
	for(i=0;i<d;i++)
	{
		ans=dis[end[i]]<ans?dis[end[i]]:ans;
	}
	return ans;
}
int main()
{
	int a,b,c,i,start,min,flag;
	while(scanf("%d%d%d",&t,&s,&d)!=EOF)
	{
		max=0;
		min=INF;
		//memset(map,INF,sizeof(map));第一处 
		for(i=0;i<1001;i++)
		{
			for(j=0;j<1001;j++)
			{
				map[i][j]=INF;
			}
		}
		while(t--)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(a>max)max=a;
			if(b>max)max=b;
			if(map[a][b]>c)
			map[a][b]=map[b][a]=c;
		}
		for(i=0;i<s;i++)
		{
			scanf("%d",&start);
			map[0][start]=0;
		}
		for(i=0;i<=max;i++)
		{
			for(j=0;j<=max;j++)
			{
				//if(map[i][j]<INF)printf("map[%d][%d]==%d\n",i,j,map[i][j]);
			}
		}
		for(i=0;i<d;i++)
		{
			scanf("%d",&end[i]);
		}
		//for(k=0;k<s;k++)
		{
			flag=dijstra(0);
			min=min<flag?min:flag;
		}
		printf("%d\n",min);
	}
	return 0;
}
以上代码还有几点要说的

第一处:大神指点,memset赋个-1、0、1什么的还行,要想赋infinity,乖乖用for吧……(上一道题就没出现这个问题╮(╯_╰)╭不知道是不是上一个题数组小的原因)

第二处:上网查得bool型变量初值为0(false),结果没初始化,后果可想而知TAT……

第三处:上个题的代码里有这句(模板里抄来的),现在仔细分析一下。这句的意思应该是“如果当前最短路距离为0,或者无穷大,跳出循环”,无穷大时跳出好理解,就是当前点不与任何没走过的点相连,再往下走也找不到路了,用在此题中逻辑也没有问题,所以加上也能A(试过),但距离为0这句就不知为何了,放在此题中是显然不行,因为0与起点的距离是0,加上必wrong。

另外,代码改动较多,也比较难看,为复习时看得到以前的错误,注释都保留下来了,下面是精简版:

#include<stdio.h>
#define INF 0x7fffffff
int t,s,d,end[1001],max,map[1001][1001],i,j;
int dijstra(int sta)
{
	bool vis[1001];
	int dis[1001];
	for(i=0;i<1001;i++)dis[i]=INF,vis[i]=false;
	for(i=0;i<max;i++)
	{
		dis[i]=map[sta][i];
	}
	dis[0]=0;
	vis[sta]=true;
	for(i=0;i<max;i++)
	{
		int mark=sta,temp=INF;
		for(j=1;j<=max;j++)
		{
			if(!vis[j]&&sta!=j)
			{
				if(map[sta][j]<INF&&dis[j]>dis[sta]+map[sta][j])
				{
					dis[j]=dis[sta]+map[sta][j];
				}
				if(dis[j]<temp)
				{
					temp=dis[j];
					mark=j;
				}
			}
		}
		if(temp==INF)break;
		vis[mark]=true;
		sta=mark;
	}
	int ans=INF;
	for(i=0;i<d;i++)
	{
		ans=dis[end[i]]<ans?dis[end[i]]:ans;
	}
	return ans;
}
int main()
{
	int a,b,c,i,start;
	while(scanf("%d%d%d",&t,&s,&d)!=EOF)
	{
		max=0;
		for(i=0;i<1001;i++)
		{
			for(j=0;j<1001;j++)
			{
				map[i][j]=INF;
			}
		}
		while(t--)
		{
			scanf("%d%d%d",&a,&b,&c);
			if(a>max)max=a;
			if(b>max)max=b;
			if(map[a][b]>c)
			map[a][b]=map[b][a]=c;
		}
		for(i=0;i<s;i++)
		{
			scanf("%d",&start);
			map[0][start]=0;
		}
		for(i=0;i<d;i++)
		{
			scanf("%d",&end[i]);
		}
		printf("%d\n",dijstra(0));
	}
	return 0;
}
PS:将近两天,现在已经是第三天凌晨了,A掉这个题,可以好好睡一觉了……(~ o ~)~zZ



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值