UVa 10047 - The Monocycle

题目:在一个n*m的迷宫中有一个轮子,轮子的每个72°的扇面被涂上一种不同的颜色。

            轮子可以移动到上下左右四个方向的格子中,每次移动到相邻格子中,轮子转动72°。

            每个单位时间轮子可以做两种运动:

            1.移动到相邻格子;2.改变朝向,面向原来的左、右方(朝向改变90°),但不转动。

            初始时轮子在'S'格子中,面向西方,并且绿色的中央接触地面,

            求到达'T'格子时,还是绿色的中央接触地面的情况的最短时间。('#'的格子不能移动)

分析:bfs,搜索,最短路。状态 f(行坐标:x,列坐标:y,方向:f,接触地面的颜色:c)

            求解状态f(x,y,f,c)到达的最短时间,用bfs求解即可。

            每个点可能走过不只一次(方向和接触地面的颜色不同),但每个状态只能走一次。

说明:这个题目比较裸,设计好状态即可直接求解。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

typedef struct node_s{
	int x,y,f,c,t;
	node_s(){}
	node_s( int a, int b ){x = a;y = b;}
	node_s( int X, int Y, int F, int C, int T ) {
		x = X;y = Y;f = F;c = C;t = T;
	}
}snode;
snode Q[12520],Now;

char maps[32][32];
int  visit[32][32][4][5];

/* 上右下左,编号为0123 */
int  dxy[4][2] = {-1,0,0,1,1,0,0,-1};
int  bfs( int n, int m, snode S, snode T )
{
	memset( visit, 0 ,sizeof(visit) );
	
	int move = 0,save = 0,xx,yy;
	Q[save] = snode( S.x, S.y, 0, 0, 1 );
	visit[Q[save].x][Q[save].y][Q[save].f][Q[save].c] = 1;
	save ++;
	
	while ( move < save ) {
		Now = Q[move ++];
		/*向左侧转动*/
		if ( !visit[Now.x][Now.y][(Now.f+3)%4][Now.c] ) {
			visit[Now.x][Now.y][(Now.f+3)%4][Now.c] = Now.t+1;
			Q[save ++] = snode( Now.x, Now.y, (Now.f+3)%4, Now.c, Now.t+1 );
		}
		/*向右侧转动*/
		if ( !visit[Now.x][Now.y][(Now.f+1)%4][Now.c] ) {
			visit[Now.x][Now.y][(Now.f+1)%4][Now.c] = Now.t+1;
			Q[save ++] = snode( Now.x, Now.y, (Now.f+1)%4, Now.c, Now.t+1 );
		}
		/*向前移动*/
		xx = Now.x + dxy[Now.f][0];
		yy = Now.y + dxy[Now.f][1];
		if ( xx >= 0 && xx < n && yy >= 0 && yy < m )
		if ( maps[xx][yy] != '#' && !visit[xx][yy][Now.f][(Now.c+1)%5] ) {
			visit[xx][yy][Now.f][(Now.c+1)%5] = Now.t+1;
			Q[save ++] = snode( xx, yy, Now.f, (Now.c+1)%5, Now.t+1 );
		}
	}
	
	int Min = 100000;
	for ( int i = 0 ; i < 4 ; ++ i )
		if ( visit[T.x][T.y][i][0] && Min > visit[T.x][T.y][i][0] )
			Min = visit[T.x][T.y][i][0];
	if ( Min != 100000 )
		printf("minimum time = %d sec\n",Min-1);
	else
		printf("destination not reachable\n");
	return 0;
}

/* 寻找起点和终点 */
snode findS( int n, int m, char c )
{
	for ( int i = 0 ; i < n ; ++ i )
	for ( int j = 0 ; j < m ; ++ j )
		if ( maps[i][j] == c )
			return snode( i, j );	
}

int main()
{
	int n,m,t = 0,ans;
	while ( scanf("%d%d",&n,&m) && n+m ) {
		if ( t ++ ) printf("\n");
		
		for ( int i = 0 ; i < n ; ++ i )
			scanf("%s",maps[i]);
		
		printf("Case #%d\n",t);
		bfs( n, m, findS( n, m, 'S' ), findS( n, m, 'T' ) );
	}
	return 0;
}

测试数据:

1 3
S#T
10 10
#S.......#
#..#.##.##
#.##.##.##
.#....##.#
##.##..#.#
#..#.##...
#......##.
..##.##...
#.###...#.
#.....###T
5 5
#S#..
#.#..
#.###
#...T
#####
10 10
S.........
..........
..........
..........
..........
..........
..........
..........
..........
........T.
3 3
ST#
##.
.#.
25 25
S........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
.........................
........................T
6 6
#.#...
#.S.#.
#####.
#..#..
#T##..
......
5 10
.S........
..##.....#
..#...T...
..#.......
..#.......
15 15
S......#.......
.......#.......
......#.#....T.
......#..#.....
.....#...#.....
....#.....#...#
....#.#.#.#....
....#..#...#...
...#..##.#.#...
...#...#....#..
..#..#.#....#..
..#.#..#.....#.
.##..#.#.....#.
...#...#.....#.
#......#.......
1 10
.S.....T..
1 3
S#T
10 10
#S.......#
#..#.##.##
#.##.##.##
.#....##.#
##.##..#.#
#..#.##...
#......##.
..##.##...
#.###...#.
#.....###T
5 5
#S#..
#.#..
#.###
#...T
#####
10 10
S.........
..........
..........
..........
..........
..........
..........
..........
..........
........T.
3 3
ST#
##.
.#.
6 6
#.#...
#.S.#.
#####.
#..#..
#T##..
......
4 7
##....T
##.###.
S..###.
##.....
4 7
##.....
##.###.
S..###.
##....T
0 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值