{POJ}{3897}{Maze Stretching}{二分答案+BFS}
题意:给定迷宫,可以更改高度比,问如何使最短路等于输入数据。
思路:由于是单调的,可以用二分答案,然后BFS验证。这里用优先队列,每次压入也要进行检查(dis大小)防止数据过多,A*也可以。好久不写图论,WA成狗
#include <iostream> #include <string> #include <cstring> #include <cstdio> #include <algorithm> #include <memory> #include <cmath> #include <bitset> #include <queue> #include <vector> #include <stack> using namespace std; #define CLR(x,y) memset(x,y,sizeof(x)) #define MIN(m,v) (m)<(v)?(m):(v) #define MAX(m,v) (m)>(v)?(m):(v) #define ABS(x) ((x)>0?(x):-(x)) #define rep(i,x,y) for(i=x;i<y;++i) #define SET_NODE(no,a,b,c) {no.x=a;no.y=b;no.val=c;} const int MAXN = 200; const double INF = 1<<30; const double EPS = 0.000001; int dir[4][2]={1,0,-1,0,0,1,0,-1}; int n,m; int tag[MAXN]; char g[MAXN][MAXN]; double dist; bool visit[MAXN][MAXN]; double dis[MAXN][MAXN]; typedef struct { int x,y; double val; }Node; Node s,e,node; bool operator < (const Node& a,const Node& b) { return a.val > b.val; } bool check(const int& x, const int& y) { if(x<0||x>=n) return false; if(y<0||y>=m) return false; if(g[x][y] == '#') return false; if(visit[x][y]) return false; return true; } double BFS(double len) { int i,j,k; Node tmp; priority_queue<Node> q; q.push(s); CLR(visit,0); rep(i,0,n) rep(j,0,m) dis[i][j] = INF; while(!q.empty()) { node = q.top(); q.pop(); visit[node.x][node.y] = true; if(node.x == e.x && node.y == e.y) return node.val; if(check(node.x+1,node.y)){ SET_NODE(tmp,node.x+1,node.y,node.val+len); if(tmp.val<dis[tmp.x][tmp.y]) { dis[tmp.x][tmp.y] = tmp.val; q.push(tmp); } } if(check(node.x-1,node.y)){ SET_NODE(tmp,node.x-1,node.y,node.val+len); if(tmp.val<dis[tmp.x][tmp.y]) { dis[tmp.x][tmp.y] = tmp.val; q.push(tmp); } } if(check(node.x,node.y+1)){ SET_NODE(tmp,node.x,node.y+1,node.val+1); if(tmp.val<dis[tmp.x][tmp.y]) { dis[tmp.x][tmp.y] = tmp.val; q.push(tmp); } } if(check(node.x,node.y-1)){ SET_NODE(tmp,node.x,node.y-1,node.val+1); if(tmp.val<dis[tmp.x][tmp.y]) { dis[tmp.x][tmp.y] = tmp.val; q.push(tmp); } } } return 0; } void Solve() { int i,j,k,t,tt; scanf("%d",&tt); rep(t,1,tt+1){ scanf("%lf%d",&dist,&n); rep(i,0,n) { getchar(); gets(&g[i][0]); } m = strlen(g[0]); rep(i,0,n) rep(j,0,m) if(g[i][j]=='S') { s.x = i; s.y = j; }else if (g[i][j]=='E') { e.x = i; e.y = j; } s.val = 0; double low = 0; double high = 10; double mid = (low+high)/2; double res = 0; while(ABS(low-high)>EPS) { mid = (low+high)/2; res = BFS(mid); //printf("[%f %f %f]\n",mid,res,dist); if(res < dist+EPS) low = mid ; else high = mid; } printf("Case #%d: %.3f%%\n",t,mid*100); } } int main() { Solve(); return 0; }