【图论】【启发式搜索】【二分查找】[POJ 3897]Maze Stretching
启发式搜索主要就是加速,其实不用也可以过。二分L然后每次看最短路是多少,估价函数就是曼哈顿距离,然后注意精度误差就好了Tip:在POJ上交这道题目记得用c++千万不要用g++
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 100;
const double eps = 1e-6;
double f[MAXN+5][MAXN+5], L;
int n, m;
char Map[MAXN+5][MAXN+5];
struct State{
int x, y;
double f, g, h;
bool operator < (const State &s) const {
return f > s.f;
}
};
priority_queue<State> que;
double mabs(double d){return d>0?d:-d;}
double _h(State s, int tox, int toy, int p){
return 1.0 * mabs(s.x - tox) * p + 1.0 * mabs(s.y - toy);
}
double Astar(int stx, int sty, int tox, int toy, double P){
while(!que.empty()) que.pop();
for(int i=1;i<=100;i++)
for(int j=1;j<=100;j++)
f[i][j] = 100000000;
State tmp, tmp2;
tmp.x = stx, tmp.y = sty;
tmp.g = 0, tmp.h = _h(tmp, tox, toy, P);
tmp.f = tmp.g + tmp.h;
f[tmp.x][tmp.y] = tmp.f;
que.push(tmp);
while(!que.empty()){
tmp = que.top(); que.pop();
if(tmp.x == tox && tmp.y == toy)
return tmp.g;
if(tmp.x > 1 && Map[tmp.x-1][tmp.y] != '#'){
tmp2 = tmp; tmp2.x --;
tmp2.g += P; tmp2.h = _h(tmp2, tox, toy, P);
tmp2.f = tmp2.g + tmp2.h;
if(tmp2.f < f[tmp2.x][tmp2.y]){
f[tmp2.x][tmp2.y] = tmp2.f;
que.push(tmp2);
}
}
if(tmp.x < n && Map[tmp.x+1][tmp.y] != '#'){
tmp2 = tmp; tmp2.x ++;
tmp2.g += P; tmp2.h = _h(tmp2, tox, toy, P);
tmp2.f = tmp2.g + tmp2.h;
if(tmp2.f < f[tmp2.x][tmp2.y]){
f[tmp2.x][tmp2.y] = tmp2.f;
que.push(tmp2);
}
}
if(tmp.y > 1 && Map[tmp.x][tmp.y-1] != '#'){
tmp2 = tmp; tmp2.y --;
tmp2.g += 1; tmp2.h = _h(tmp2, tox, toy, P);
tmp2.f = tmp2.g + tmp2.h;
if(tmp2.f < f[tmp2.x][tmp2.y]){
f[tmp2.x][tmp2.y] = tmp2.f;
que.push(tmp2);
}
}
if(tmp.y < m && Map[tmp.x][tmp.y+1] != '#'){
tmp2 = tmp; tmp2.y ++;
tmp2.g += 1; tmp2.h = _h(tmp2, tox, toy, P);
tmp2.f = tmp2.g + tmp2.h;
if(tmp2.f < f[tmp2.x][tmp2.y]){
f[tmp2.x][tmp2.y] = tmp2.f;
que.push(tmp2);
}
}
}
return -1.0;
}
int Tcnt;
void solve(){
memset(Map, 0, sizeof Map);
scanf("%lf%d\n", &L, &n);
double l = 0.0, r = 10.0, mid, len, sx, sy, ex, ey, P;
for(int i=1;i<=n;i++){
gets(Map[i]+1);
}
m = strlen(Map[1] + 1);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(Map[i][j] == 'S'){
sx = i, sy = j;
}else if(Map[i][j] == 'E'){
ex = i, ey = j;
}
}
}
while(l < r){
mid = (l + r) / 2.0;
len = Astar(sx, sy, ex, ey, mid);
if(len+eps >= L && len-eps <= L){
P = mid;
break;
}else if(len > L){
r = mid;
}else{
l = mid;
}
}
printf("Case #%d: %.3lf%%\n", ++Tcnt, P*100.0);
}
int main(){
int K;
scanf("%d", &K);
while(K--){
solve();
}
return 0;
}