HDU 5433 Xiao Ming Climbing (DIjksta最短路+細節)*
阿新 • • 發佈:2018-12-13
#include<bits/stdc++.h> using namespace std; #define debug puts("YES"); #define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++) #define read(x,y) scanf("%d%d",&x,&y) #define ll long long #define lrt int l,int r,int rt #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define root l,r,rt typedef pair<int,int> pii; const int maxn =50+7; const int mod=1e9+7; const double INF =1e20+7; const double EPS=1e-6; ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;} ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} /* 題目大意:在一張地圖上給定初始位置 和終點位置,和一個初始化能量, 每走一格需要消耗一個能量, 走一格獲得的權重是兩格高度差除以當前能量值, 問走到終點在能量格允許的情況下所收穫權重最小是多少。 以前的標準最短路只需要二維就可以標記狀態, 現在要多一個維度k,用優先佇列最小堆去擴充狀態, 所以走過的三維狀態就沒必要走第二次,(堆裡最多有50^3個狀態) 然後用當前的狀態去進行差分約束, 更新周圍的狀態,如果更新成功,則那個狀態又成為了新的擴充套件狀態。 最後的答案是通過列舉k來得到的,注意k為0是個不可行狀態。 一些細節:k可以為0...所以在判定的時候注意下。 */ char ch[maxn]; int n,m,k,mp[maxn][maxn]; int sx,sy,ex,ey; struct node { int x,y,s;///步數 double v;///權重 bool operator<(const node& y) const { return v>y.v; } }; int dx[]={0,0,1,-1},dy[]={1,-1,0,0};///方向陣列 bool judge(int x,int y) { if(x<=0||x>n) return false; if(y<=0||y>m) return false; return true; } bool Eq(double x,double y){return abs(x-y)<=EPS;} double cnt(int x1,int y1,int x2,int y2,int kk){return 1.0*abs(mp[x1][y1]-mp[x2][y2])/(1.0*kk);} double d[maxn][maxn][maxn]; int done[maxn][maxn][maxn]; void spfa(int sx,int sy) { priority_queue<node> pq; pq.push(node{sx,sy,k,0}); memset(done,0,sizeof(done)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int q=0;q<=k;q++) d[i][j][q]=INF;d[sx][sy][k]=0;///初始化距離陣列 while(!pq.empty()) { node tp=pq.top();pq.pop(); int x=tp.x,y=tp.y,s=tp.s; if(done[x][y][s]) continue; done[x][y][s]=1; for(int i=0;i<4;i++) { int tx=x+dx[i]; int ty=y+dy[i]; int ts=s-1; if(!judge(tx,ty)) continue;///越界 if(mp[tx][ty]==-1) continue; if(ts<=0) continue; double tmp=cnt(tx,ty,x,y,s)+d[x][y][s]; if(d[tx][ty][ts]>tmp) { d[tx][ty][ts]=tmp; pq.push(node{tx,ty,ts,tmp}); } } } double ans=INF; for(int i=1;i<=k;i++) ans=min(ans,d[ex][ey][i]); if(!Eq(ans,INF)) printf("%.2f\n",ans); else puts("No Answer"); } int main() { int t;scanf("%d",&t); while(t--) { scanf("%d%d%d",&n,&m,&k); for(int i=1;i<=n;i++) { scanf("%s",ch+1); for(int j=1;j<=m;j++) { if(ch[j]=='#') mp[i][j]=-1; else mp[i][j]=ch[j]-'0'; } } scanf("%d%d",&sx,&sy); scanf("%d%d",&ex,&ey); spfa(sx,sy); } return 0; }