DFS超时,当时头脑混乱不会改成BFS。过了两天,思路清晰,一次AC,真爽。
思路:用dp[x][y][p]表示走到(x,y)且剩余斗志为p的最少体力,bfs的过程中,只有满足边界条件并且下一步算出来的值要小于dp[next.x][next.y][next.p]时才把这个点放入队列。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <stack> #include <cmath> #include <queue> #include <set> #include <map> typedef long long ll; using namespace std; const int inf=0x3f3f3f3f; const int maxn=1e6+10; char g[55][55]; double dp[55][55][55],ans; int dir[4][2]={-1,0,0,-1,1,0,0,1}; int n,m,p,sx,sy,ex,ey; struct Point{ int x,y,p;//坐标及当前斗志 double lost;//当前消耗体力 }; void bfs(Point start){ queue<Point>q; q.push(start); while(!q.empty()){ Point now=q.front(); q.pop(); if(now.x==ex && now.y==ey && now.p>0){ ans=min(ans,now.lost); //printf("end at:%d %d\n",ex,ey ); } Point next; for(int i=0;i<4;++i){ next.x=now.x+dir[i][0]; next.y=now.y+dir[i][1]; next.p=now.p-1; if(next.x>0 && next.x<=n && next.y>0 && next.y<=m && g[next.x][next.y]!='#' && next.p>0 ){ next.lost=now.lost+ (double)1.0*abs(g[now.x][now.y]-g[next.x][next.y])/now.p; if(next.lost < dp[next.x][next.y][next.p]){ dp[next.x][next.y][next.p]=next.lost; q.push(next); //printf("push : %d %d\n",next.x,next.y ); } } } } } int main() { int t; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=n;++i){ getchar(); for(int j=1;j<=m;++j){ char ch=getchar(); g[i][j]=ch; //printf("%c",g[i][j] ); } //printf("\n"); } scanf("%d%d%d%d",&sx,&sy,&ex,&ey); ans=1e8; for(int i=1;i<=n;i++){ for(int j=1;j<=m;++j){ for(int k=1;k<=p;k++){ dp[i][j][k]=1e8; } } } Point tmp; tmp.x=sx; tmp.y=sy; tmp.p=p; tmp.lost=0; bfs(tmp); if(ans==1e8)printf("No Answer\n"); else printf("%.2f\n",ans ); } return 0; }
来源:https://www.cnblogs.com/bruce27/p/4814350.html