poj 3328 Cliff Climbing 题解

做了这道题目,感觉纯搜索更上一次楼啦。

题意:

计算从起点 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;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值