UVa 10047 - The Monocycle, 优先队列+BFS

来源:互联网 发布:c 数组删除指定元素 编辑:程序博客网 时间:2024/05/01 02:23

FILE10047 - The Monocycle3148

35.90%
1014
77.12%
题目链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=105&page=show_problem&problem=988


题目类型:搜索,优先队列


题目:

A monocycle is a cycle that runs on one wheel and the one we will be considering is a bit more special. It has a solid wheel colored with five different colors as shown in the figure:

The colored segments make equal angles (72o) at the center. A monocyclist rides this cycle on an $M \times N$ grid of square tiles. The tiles have such size that moving forward from the center of one tile to that of the next one makes the wheel rotate exactly 72o around its own center. The effect is shown in the above figure. When the wheel is at the center of square 1, the mid­point of the periphery of its blue segment is in touch with the ground. But when the wheel moves forward to the center of the next square (square 2) the mid­point of its white segment touches the ground.

Some of the squares of the grid are blocked and hence the cyclist cannot move to them. The cyclist starts from some square and tries to move to a target square in minimum amount of time. From any square either he moves forward to the next square or he remains in the same square but turns 90o left or right. Each of these actions requires exactly 1 second to execute. He always starts his ride facing north and with the mid­point of the green segment of his wheel touching the ground. In the target square, too, the green segment must be touching the ground but he does not care about the direction he will be facing.

Before he starts his ride, please help him find out whether the destination is reachable and if so the minimum amount of time he will require to reach it.


题目大意翻译:

有一个独轮车,轮子上有5个不同的扇形颜色区域, 每个区域大小都是相等的(72°扇形)。 骑着这个车子在一个广场上行走。

广场是有大小相同的正方形瓷砖铺成的。 独轮车从一块瓷砖走向相邻的一块,轮子正好转72°。只能走向相邻的上、下、左、右的瓷砖。从一个瓷砖走向下一个瓷砖耗费1秒钟。车子转方向90°耗费1秒钟,连转180°就要费2秒钟。白色的瓷砖可以走,黑色的不可以走(黑色的用"#"代替,白色的用"."代替)。


题目要求从标有S的地方走向标有T的地方。轮子在开始时,蓝色是贴着地面的,要求到达终点时,也正好是蓝色贴着地面的。

如果可以到达的话,输出所需要的最短时间。否则输出 destination not reachable。 


样例输入:

1 3S#T10 10#S.......##..#.##.###.##.##.##.#....##.###.##..#.##..#.##...#......##...##.##...#.###...#.#.....###T0 0

样例输出:

Case #1destination not reachable Case #2minimum time = 49 sec



分析与总结:

刚开始时,我的思路是用贪心的思想,直接用BFS搜索最短路径到达终点, 到了终点后,检查颜色是否是符合的,如果不符合的话,就在终点处周围走几步再走回终点,让颜色正确。但这样的思路是有问题的,不能得出正确答案。看下图就明白了。


这个是直接BFS搜到终点的路径, 到路径后发现颜色是不对的,于是只能按原路走回几步,然后再走回终点。但是得到的答案是错的,比正确的多了2秒。

而正确的路径是这样的:


这个路径到达终点后正好颜色是对的。 

上面之所以会多了2秒,是因为到了终点在直接退回去,要转弯180°,耗费2秒时间,走了几步又要180°转弯,再耗费2秒。 虽然最终走的步数是一样的,但是比正确路径多了两次弯。


这个思路不可行。 然后又苦思冥想的很久,发现还是没想到好方法。于是暂时放下。

2天后,这个专题只剩下这最后一题。

于是邪恶的上网搜了下解题报告,看了下别人的思路,于是才知道这题要用到优先队列,于是才知道还要多维的状态。


一般的BFS,访问后就在vis数组上标记为以访问,然后就不能再访问这个地方了。但是这题一个格子可以访问多次,所以不能再用一维来表示状态了。

这题的每个状态应该是还有方向,颜色, 在一个格子上,走过的方向,并且当前颜色和之前走过的相同,就不能再次访问。



#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<queue>using namespace std;int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}}; // 上0,右1,下2,左3int M,N,start_x, start_y,end_x,end_y, step;char map[30][30];bool  vis[30][30][4][5]; //前2维代表坐标,后2维代表方向和颜色的状态struct Node{    int x,y;    int color;  // 绿0,白1,黑2,红3,蓝4    int time;    int dir; // 当前指向的方向    friend bool operator < (const Node &a, const Node &b){ // 重载<构建最小堆        return a.time > b.time;     }};Node begin, q, t;priority_queue<Node >que;void bfs(){    while(!que.empty()) que.pop();    que.push(begin);    vis[begin.x][begin.y][begin.dir][begin.color] = true;    while(!que.empty()){        q = que.top();        que.pop();        for(int i=0; i<4; ++i){            int dx = q.x+dir[i][0];            int dy = q.y+dir[i][1];                        if(dx>=0 && dx<M && dy>=0 && dy<N && map[dx][dy]!='#'){                if(q.dir==i){                    t.time = q.time+1;                    t.dir=i;                    t.x=dx, t.y=dy;                    t.color = (q.color+1)%5;                }                else{                    if(abs(q.dir-i)==2)                        t.time = q.time+2;                    else                         t.time = q.time+1;                    t.dir = i;                    t.x=q.x, t.y=q.y;                    t.color = q.color;                }                if(!vis[t.x][t.y][i][t.color]){                    if(t.x==end_x && t.y==end_y && t.color==0){                        printf("minimum time = %d sec\n", t.time);                        return;                    }                    que.push(t);                    vis[t.x][t.y][i][t.color] = true;                }            }        }    }    printf("destination not reachable\n");}int main(){#ifdef LOCAL    freopen("input.txt","r",stdin);#endif     int cas=1;    while(~scanf("%d %d%*c", &M, &N) && M && N){              bool isFind_S=false, isFind_T=false;         memset(vis, 0, sizeof(vis));        for(int i=0; i<M; ++i){            gets(map[i]);            if(!isFind_S || !isFind_T){                for(int k=0; k<strlen(map[i]); ++k){                    if(map[i][k]=='S'){                        start_x=i,start_y=k; isFind_S=true;                     }                     if(map[i][k]=='T'){                        end_x=i, end_y=k; isFind_T=true;                    }                }            }        }           begin.x=start_x, begin.y=start_y, begin.color=0, begin.time=0;        begin.dir=0;        if(cas!=1) printf("\n");        printf("Case #%d\n", cas++);        bfs();    }    return 0;}


附加测试样例input

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##..
......
0 0


附加测试样例output:

Case #1
minimum time = 19 sec

Case #2
minimum time = 82 sec

Case #3
minimum time = 13 sec

Case #4
destination not reachable

Case #5
minimum time = 49 sec

Case #6
minimum time = 17 sec

Case #7
minimum time = 30 sec

Case #8
minimum time = 14 sec

Case #9
minimum time = 30 sec


——      生命的意义,在于赋予它意义。 

                   原创 http://blog.csdn.net/shuangde800 , By   D_Double