Silver Cow Party (dijk)

Silver Cow Party

One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1…N is going to attend the big cow party to be held at farm #X (1 ≤ XN). A total of M (1 ≤ M≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requires Ti (1 ≤ Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow’s return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

翻译:

来自 n 个农场(1≤n≤1000)的1. .n头奶牛将参加农场 x(1≤x≤n)举办的大型奶牛派对。共有m(1≤m≤100000)单向(单向道路连接成对农场);i 号公路需要 Ti(1≤Ti≤100)单位的穿越时间。
每头牛都必须走到派对上,派对结束后,回到自己的农场。每头母牛都懒惰,因此选择了一条时间最短的最佳路线。一头牛的返回路线可能不同于她最初去派对的路线,因为道路是单向的。
在所有的奶牛中,一头奶牛步行去聚会和回来必须花多长时间?

input

Line 1: Three space-separated integers, respectively: N, M, and X
Lines 2… M+1: Line i+1 describes road i with three space-separated integers: Ai,Bi, and Ti. The described road runs from farm Ai to farm Bi, requiring Ti time units to traverse.

翻译:

第1行:三个空格分隔的整数,分别为:n、m和x
第2…M+1行:第 i+1行用三个空格分隔的整数(ai、bi和ti)描述了道路I。所描述的道路从农场ai到农场bi,需要Ti时间单位进行穿越。

output

Line 1: One integer: the maximum of time any one cow must walk.

第1行:一个整数:任何一头牛必须行走的最长时间。

Sample Input

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

Sample output

10

Hint

Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.

翻译:

奶牛4直接进入一方(3个单位),通过农场1和3(7个单位)返回,总共10个时间单位。

一个比较基础的dijkstra 算法问题,就是要注意他是要求的是一来一回的总共最大时间,而且路都是单向的。先计算x农场到其他农场用的最短时间,在枚举其他农场到x农场的最短时间,记录下最大来回时间。但是要注意时间复杂度,小心超时,所以我这里用了一个转置矩阵,交换 map[i][j] 与 map[j][i] 的值,这样就能避免超时。

代码如下
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf= 99999999;
int dis1[1111],dis[1111],map[1111][1111],visit[1111];
int m,n,x,a,b,t,i,j,k,minx,temp,v,ans=0;
void dijkstra()
{
	memset(visit,0,sizeof(visit));       //初始化visit数组 
	for(i=1;i<=n;i++)
	    dis[i]=map[x][i];      //初始化 
	visit[x]=1;
	v=x;
	for(k=2;k<=n;k++)                     //求出距离x  最近的一个 牛场 并记录下来 
	{
		minx=inf;
		for(j=1;j<=n;j++)
		{
			if(!visit[j]&&dis[j]<minx)
		  {
			minx=dis[j];
			v=j;
		   }
		}
		visit[v]=1;
		for(i=1;i<=n;i++)              //求出各个 牛场  到x  的最短距离 
		    if(!visit[i]&&dis[i]>dis[v]+map[v][i])
		        dis[i]=dis[v]+map[v][i];
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&x);     //输入 
	for(i=1;i<=n;i++)                 //将数组map 初始化 
	    for(j=1;j<=n;j++)
	   {
	   	    if(i==j)
	   	        map[i][j]=0;
	   	    else
	   	        map[i][j]=inf;
	   }
	for(i=0;i<m;i++)            //输入道路信息,并储存在map中 
    {
    	scanf("%d%d%d",&a,&b,&t);
    	if(t<map[a][b])
    	map[a][b]=t;
	}
	dijkstra();   //第一次调用,得出x  到 其他牛场的最短时间 
	for(i=1;i<=n;i++)   //储存第一次调用得到的值 
	   dis1[i]=dis[i];
	for(i=1;i<=n;i++)     //最重要的!!转置矩阵,也就是交换map[i][j]与map[j][i]的值 
	    for(j=i+1;j<=n;j++)   //相当于把求其他农场到x  的距离   转换成了求  x  到其他牛场的距离 
	    {
		    temp=map[i][j];
		    map[i][j]=map[j][i];
		    map[j][i]=temp;
	    }
	dijkstra();        //第二次调用 ,再求 x 到其他牛场的距离 
	for(i=1;i<=n;i++)
	   if(i!=x)
	        ans=max(ans,dis1[i]+dis[i]);     //求出两次调用结果之和最大 
	printf("%d\n",ans);         //输出 
	return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
这段代码是一个基于A*算法的路径规划算法的实现。下面逐行解释: ``` if astar == false ``` 如果不使用A*算法,则执行以下代码。 ``` while (~all(unvisited(:)==inf)) ``` 当存在未访问的节点时,执行以下代码。 ``` dist_unvisited = dist.*unvisited; [~, id] = min(dist_unvisited(:)); unvisited(id) = inf; ``` 计算未访问节点的距离,并选择距离最短的节点作为当前节点,将其标记为已访问。 ``` num_expanded = num_expanded + 1; [i,j,k] = ind2sub([map.nx,map.ny,map.nz],id); ``` 将当前节点的索引转化为三维坐标。 ``` for d = 1:size(dijk,1) nijk = bsxfun(@plus, int32([i,j,k]), int32(dijk(d,:))); if all(nijk > 0) & all(int32([map.nx, map.ny, map.nz]) >= int32(nijk)) ... & unvisited(nijk(1),nijk(2),nijk(3)) == 1 ... & map.occ_map(nijk(1),nijk(2),nijk(3)) ~= 1 alt = dist(id) + sqrt(sum(dijk(d,:).^2)); nid = (nijk(3)-1)*map.nx*map.ny + (nijk(2)-1)*map.nx + nijk(1); if alt < dist(nid) dist(nid) = alt; prev(nijk(1), nijk(2), nijk(3),:) = [i,j,k]; end end end ``` 遍历当前节点的所有相邻节点,并计算其到起始点的距离和到目标点的估计距离,称为启发式距离。如果相邻节点的距离小于当前距离,则更新相邻节点的距离和前驱节点。这里的`dijk`是一个3x3x3的矩阵,表示相邻节点的相对位置。 ``` if id == (goal(3)-1)*map.nx*map.ny + (goal(2)-1)*map.nx + goal(1); break end ``` 如果当前节点是目标节点,则退出循环。最终的路径可以通过`prev`数组回溯得到。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的小朱同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值