スキーPOJ 3037非常に奇妙な最短経路問題
問題の意味
質問の意味:あなたは、グリッド内の任意の2点間を費やした時間を計算することができ左上隅から右下隅に必要な最小限の時間に来て、今お聞きし、グリッドの左上隅にR * Cです。
問題解決のためのアイデア
必要性は、選択したパスの他のポイントへの左上から、つまり、法律を見つけるために、その時点での到着率が固定されています。
例えば、次の行列の1:
1 5 3
6 3 5
2 4 3
我々は、点2の速度のために見つけることができる値を計算する、次いで、\ [V_2 V_1 = 2 ^ {1-2} * \] 、ようであるパス\ [1-> 6> 2 \] 、次に\ 【V_2 V_1 = ^ * 2 * 2 ^ {1-6} {6-2} * V_1 = 2 ^ {1-2} \]。私たちは他の点の速度を知ることができるように。
コードの実装は、これは兄への参照である、非常に奇妙です\(LHMの\)学生コード、非常に悪い学生、そして後に臨床医学を回し、と彼のチームは、ゲームをプレイしたいと思うが、自分自身を見つけるために、彼を祝福プロのように、結局、それはプロ回すために、また、コンピュータの専門家にプロのターンであるだけでなく、自分自身の感情を持っています。
コードの実装
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
struct node{
int x,y;
double time;
bool operator < (const node& tmp) const
{
return time > tmp.time;
}
};
double v;
int n,m;
int book[110][110],a[110][110];
priority_queue<node>q;
int next[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
void bfs()
{
while(!q.empty()) q.pop();
q.push((node){1,1,0.0});
while(!q.empty())
{
node t=q.top(); q.pop();
if(book[t.x][t.y]==1) continue;
book[t.x][t.y]=1;
if(t.x==n&&t.y==m)
{
printf("%.2f\n",t.time);
return ;
}
for(int i=0;i<4;i++)
{
int tx=t.x+next[i][0];
int ty=t.y+next[i][1];
if(tx>=1&&tx<=n&&ty<=m&&ty>=1&&book[tx][ty]==0)
{
double tt=t.time+1.0/(pow(2.0,(a[1][1]-a[t.x][t.y]))*v);
q.push((node){tx,ty,tt}); //注意这里加入的点没有进行标记
}
}
}
return ;
}
int main()
{
while(scanf("%lf%d%d", &v, &n, &m)!=EOF)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
}
bfs();
}
return 0;
}