Skiing POJ-3037

题目链接
在解释这道题之前,先说一下我wrong了11次,自闭四小时的原因:
我在G++下提交的,输出时double类型采用的lf,结果wrong了好久,改成了c++提交就对了

题目中文意思:
贝西和农场主约翰的其他奶牛今年冬天要去滑雪。一天,贝西发现自己在一个R(1<=R<=100)的左上角,C(1<=C<=100)的E立面网格(-25<=E<=25)。为了和FJ和其他奶牛一起参加迪斯科派对,她必须尽可能快地走到右下角只能向北、向南、向东和向西。
贝西开始以初始速度v(1<=v<=1000000)行驶。她发现了自己的速度和海拔变化之间的显著关系。当贝西从一个高度A的位置移动到相邻的4个位置B时,她的速度乘以2^(a-b)贝西从一个地点到邻近地点所花的时间是她在第一个地点时速度的倒数。
找到这两个最短的时间,这将需要贝西加入她的奶牛朋友。
输入
*第1行:三个空间分隔的整数:v、r和c,分别表示贝西的初始速度和网格中的行和列数。
*行2…r+1:c整数表示网格上相应位置的高程e。
输出
一个单独的数值,精确到小数点后两位:贝西到达网格右下角所需的最短时间。

例如:
1号点是起始点,1号点到2号点的速度是v。
1点的高度是a,2号点的高度是b,则2号点的速度为V2v2^(a-b);
3号点的高度是c,若2号点可以到3号点,则三号点的速度V3=V2
2^(b-c);
又 V2
v2^(a-b),
所以 V3=v
2^(a-b+b-c)
=v*2^(a-c)
3号点的速度可以直接由1号点求出,和2号点的高度无关。

具体内容,参看下面的代码
不会SPFA算法的请先自行百度SPFA的模板

//基于SPFA实现的二维最短路,
//使用Dijkstra算法是实现这个问题更快。
#include<queue>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int book[120][120];//spfa里面的标记数组,由二维升到一维
double map[120][120],dis[120][120],dv[120][120];
struct node
{
	int x,y;
}e,t2,temp;
//v最大是1e6,图上最多是1e4个点,则最大是1e10的数量级别,而之前经常使用的0x3f3f3f3f是1e9的级别, 太 小 
//大佬说,1e10也是个玄学问题,仔细想想啊
const double inf=1e10;
int main()
{
	double v;
	int r,c;
	scanf("%lf%d%d",&v,&r,&c);
	for(int i=1;i<=r;i++)
	for(int j=1;j<=c;j++)
	{
		scanf("%lf",&map[i][j]);
		//dv[][]存储的是这个点到它周围的其它点距离
		dv[i][j]=1.0/( v*pow(2.0,map[1][1]-map[i][j]) );
	}
	dv[1][1]=1.0/v;
	
	//初始化dis数组
	for(int i=1;i<=r;i++)
	for(int j=1;j<=c;j++)
	{
		dis[i][j]=inf;
		book[i][j]=0;
	}
	
	int tx,nx[4]={0,0,-1,1};
	int ty,ny[4]={1,-1,0,0};
	//spfa核心算法
	queue<node>q;
	dis[1][1]=0;
	book[1][1]=1;
	t2.x=1;t2.y=1;
	q.push(t2);
	
	while(!q.empty())
	{
		e=q.front();
		q.pop();
		//取消这个点的标记
		//这是为什么呢?
		//先说一下book数组的作用,
		//book数组表示哪个点被压到了队列当中。
		//现在将(e.x,e.y)弹出来了,自然要把这个点对应的book数组取消了啊
		//接着再想想,为什么要使用book这个数组呢?
		//因为对于同一个点来说,会被它四周的四个点都访问到,如果不加book数组
		//来标记这个点是否在队列中,就会被压入到队列中多次
		//那么这里为什么会赋为0也明白了吧,如果不赋为0,那么下一次的时候就不会把这个点来压倒队列里
		book[e.x][e.y]=0;
		
		for(int i=0;i<4;i++)
		{
			tx=e.x+nx[i];
			ty=e.y+ny[i];
			if(tx>r||ty>c||tx<1||ty<1) //搜索时,这里会加一条信息,book[tx][ty]==1,这里不要,因为对于一个点,会有多个点访问到它
			continue;
			
			//更新点的信息
			if(dis[tx][ty] > dis[e.x][e.y] +dv[e.x][e.y])
			{
				dis[tx][ty] = dis[e.x][e.y] + dv[e.x][e.y];
				if(book[tx][ty]==0)
				{
					book[tx][ty]=1;
					//上面还会使用e.x和e.y这个信息 
					//e.x=tx;e.y=ty;
					//q.push(e);
					temp.x=tx;temp.y=ty;
					q.push(temp);
				}
			}
		}
	}
	//这里的输出要注意:如果是G++下就要用f,C++,f和lf都行,不会可以百度  G++和C++的区别
	printf("%.2lf\n",dis[r][c]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值