做了这道题目,感觉纯搜索更上一次楼啦。
题意:
计算从起点 S 走到 终点 T 的最少耗时,范围 60*30。
走路分双脚,每次动一个脚,每次走一步有 9 个选择,耗时为 graph[x][y],即 (x, y) 坐标上的数字。其中 ‘X’ 代表不能走,只要有一个脚走到 ‘T’,就表示到终点。终点不止一个!
PS:
起点为 ‘S’,但分左右脚,即起点踏左脚,右脚就在图外,也就是说先走右脚,反之,同理。不止一个起点!
第一次用 queue 直接交了,结果 TLE,改换 priority_queue,AC。
zstu_wangrui 3328 Accepted 13860K 1250MS C++ 3601B 2013-07-20 12:38:08
算法关键:dist[60][30][60][30]
/*
poj 3328 Cliff Climbing
走格子——更上一层楼呀
多起点,多终点,分左右,9个方向的走法,格子范围:60 * 30
zstu_wangrui 3328 Accepted 13860K 1204MS C++ 2919B 2013-07-20 12:57:01
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf = 100000000;
int dd( int x ){ if( x < 0 )return -x; return x; }
int dir[9][2] = {{-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, {-1, 2}, {0, 2}, {1, 2}, {0, 3}};
struct pos{
int x, y;
};
struct Feet{
pos left, right;
int cost;
bool operator<( Feet e )const{
return e.cost < cost;
}
};
int graph[61][31], dist[61][31][61][31];
int os, w, h;
priority_queue<Feet>q;
void init()
{
int i, j, k, t, x, y;
for( i = 1; i <= h; i++ )
for( j = 1; j <= w; j++ )
for( k = 1; k <= h; k++ )
for( t = 1; t <= w; t++ )
dist[i][j][k][t] = inf;
while( !q.empty() )q.pop();
Feet id;
for( i = 1; i <= h; i++ )
{
for( j = 1; j <= w; j++ )
{
if( graph[i][j] == -1 )
{
id.left.x = i; id.left.y = j;
id.right.x = id.right.y = -1;
id.cost = 0;
q.push( id );
id.left.x = id.left.y = -1;
id.right.x = i; id.right.y = j;
id.cost = 0;
q.push( id );
}
}
}
}
int bfs()
{
init();
Feet now, to;
int i, x, y, xx, yy;
while( !q.empty() )
{
now = q.top(); q.pop();
if( now.left.x != -1 && now.right.x != -1 && (graph[now.left.x][now.left.y] == 0 || graph[now.right.x][now.right.y] == 0) )
return now.cost;
x = now.left.x;
y = now.left.y;
if( x != -1 && y != -1 )for( i = 0; i < 9; i++ )
{
xx = x + dir[i][0];
yy = y + dir[i][1];
if( xx >= 1 && xx <= h && yy >= 1 && yy <= w && graph[xx][yy] != -2 && graph[xx][yy] != -1
&& dist[x][y][xx][yy] > now.cost + graph[xx][yy] )
{
dist[x][y][xx][yy] = now.cost + graph[xx][yy];
to.cost = now.cost + graph[xx][yy];
to.left = now.left;
to.right.x = xx; to.right.y = yy;
q.push( to );
}
}
x = now.right.x;
y = now.right.y;
if( x != -1 && y != -1 )for( i = 0; i < 9; i++ )
{
xx = x + dir[i][0];
yy = y - dir[i][1];
if( xx >= 1 && xx <= h && yy >= 1 && yy <= w && graph[xx][yy] != -2 && graph[xx][yy] != -1
&& dist[xx][yy][x][y] > now.cost + graph[xx][yy] )
{
dist[xx][yy][x][y] = now.cost + graph[xx][yy];
to.cost = now.cost + graph[xx][yy];
to.left.x = xx; to.left.y = yy;
to.right = now.right;
q.push( to );
}
}
}
return -1;
}
int main()
{
int i, j;
while( ~scanf( "%d%d", &w, &h ), w + h )
{
char sign[3];
for( i = 1; i <= h; i++ )
{
for( j = 1; j <= w; j++ )
{
scanf( "%s", sign );
if( sign[0] == 'X' )
graph[i][j] = -2;
else if( sign[0] == 'T' )
graph[i][j] = 0;
else if( sign[0] == 'S' )
graph[i][j] = -1;
else
graph[i][j] = sign[0] - '0';
}
}
printf( "%d\n", bfs() );
}
return 0;
}