POJ3037 Skiing
Skiing
题目大意:
给定一个M*N的网格,已知在每个网格中的点可以向上下左右四个方向移动一个单位,每个点都有一个高度值。 从每个点开始移动时存在一个速度值,从A点移动到B点,则此时B点的速度为"A的速度*2^(A的高度值-B的高度值)",而A点移动到B点所用的时间则是A点开始移动的速度值的倒数。 提供网格的长和宽,每个点的高度,以及在左上角的点的出发速度,问从左上角的点到右下角的点最少需要多少时间。
大致思路:
这道题,我们可以注意到其实在某一个点的速度是个固定值,因为不管怎么到达该点,这个点的速度都是1/(v*(2^(起点与该点的深度差))),求出每个点的速度后,再求最短路径就好了。
代码:
1 #include<queue> 2 #include<cmath> 3 #include<cstdio> 4 #define Max_double 11258999068426240000; 5 #define N 110 6 using namespace std; 7 int d[4][2]={{0,-1},{1,0},{0,1},{-1,0}}; 8 struct hehe{ 9 int x; 10 int y; 11 }; 12 hehe p,qqq; 13 queue<hehe>q; 14 double dis[N][N]; 15 bool exist[N][N]; 16 int deep[N][N],v,n,m; 17 double spfa(){ 18 p.x=1; 19 p.y=1; 20 dis[1][1]=0; 21 exist[1][1]=1; 22 q.push(p); 23 while(!q.empty()){ 24 p=q.front(); 25 q.pop(); 26 exist[p.x][p.y]=0; 27 double k=1.0/(v*pow(2,1.0*deep[1][1]-deep[p.x][p.y])); 28 for(int i=0;i<4;i++){ 29 int x1=p.x+d[i][0],y1=p.y+d[i][1]; 30 if(x1>=1&&x1<=n&&y1>=1&&y1<=m){ 31 if(dis[x1][y1]>dis[p.x][p.y]+k){ 32 dis[x1][y1]=dis[p.x][p.y]+k; 33 if(!exist[x1][y1]){ 34 qqq.x=x1; 35 qqq.y=y1; 36 q.push(qqq); 37 exist[qqq.x][qqq.y]=1; 38 } 39 } 40 } 41 } 42 } 43 return dis[n][m]; 44 } 45 int main(){ 46 scanf("%d%d%d",&v,&n,&m); 47 for(int i=1;i<=n;i++) 48 for(int j=1;j<=m;j++){ 49 scanf("%d",&deep[i][j]); 50 dis[i][j]=Max_double; 51 } 52 printf("%.2lf",spfa()); 53 return 0; 54 }