1135飞越原野

Description

勇敢的德鲁伊法里奥出色的完成了任务之后,正在迅速的向自己的基地撤退。但由于后面有着一大群追兵,所以法里奥要尽快地返回基地,否则就会被敌人捉住。

终于,法里奥来到了最后的一站:泰拉希尔原野,穿过这里就可以回到基地了。然而,敌人依然紧追不舍。不过,泰拉希尔的地理条件对法里奥十分有利,众多的湖泊随处分布。敌人需要绕道而行,但法里奥拥有变成鹰的特殊能力,使得他能轻轻松松的飞越湖面。当然,为了保证安全起见,法里奥还是决定找一条能最快回到基地的路。

假设泰拉希尔原野是一个m*n的矩阵,它有两种地形,P表示平地,L表示湖泊,法里奥只能停留在平地上。他目前的位置在左上角(1,1)处,而目的地为右下角的(m,n)。法里奥可以向前后左右四个方向移动或者飞行,每移动一格需要1单位时间。而飞行的时间主要花费在变形上,飞行本身时间消耗很短,所以无论一次飞行多远的距离,都只需要1单位时间。飞行的途中不能变向,并且一次飞行最终必须要降落在平地上。当然,由于受到能量的限制,法里奥不能无限制的飞行,他总共最多可以飞行的距离为D。在知道了以上的信息之后,请你帮助法里奥计算一下,他最快到达基地所需要的时间。

Input

第一行是3个正整数,m(1m100)n(1n100)D(1D100)。表示原野是m*n的矩阵,法里奥最多只能飞行距离为D

接下来的m行每行有n个字符,相互之间没有空格。P表示当前位置是平地,L则表示湖泊。假定(1,1)(m,n)一定是平地。

Output

一个整数,表示法里奥到达基地需要的最短时间。如果无法到达基地,则输出impossible 

解题思路:使用广度搜索算法解决该问题。下面的算法参考了网上他人算法。首先创建一个结构体Node,用于存储状态,结构体Node的状态包括所在的位置x,y以及还能飞的距离p。从起点出发,将起点状态x=0,y=0,p=D压入deque。然后逐个取出deque中的首元素,对该元素进行四周搜索,寻找下一种合适的状态,将其压入deque中。使用3维矩阵来记录状态点是否出现过。

#include <iostream>
#include <stdio.h>
#include <deque>
#include <memory.h>
using namespace std;

struct Node{
    int x, y;       // 表示点的位置
    int p;          // 表示此时还能飞的距离
};
char graph[120][120];
bool visited[120][120][120];
int m, n, D;
int mov[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
deque<Node> q;

bool can_vis(int x, int y, int p){
    if (x >= 0 && x < m && y >= 0 && y < n && graph[x][y] == 'P' && visited[x][y][p] == false) {
        return true;
    }
    else return false;
}

int main() {
    // insert code here...
    int i,j,size;
    Node tmp, tmp1;
    int result, flag;
    while (scanf("%d",&m)!=EOF) {
        scanf("%d%d", &n,&D);
        for(i = 0; i<m; i++){
            scanf("%s",&graph[i]);
        }
        memset(visited, 0, sizeof(visited));
        
        tmp.x = 0;
        tmp.y = 0;
        tmp.p = D;
        result = 0;
        flag = 0;
        visited[tmp.x][tmp.y][tmp.p] = true;
        q.clear();
        q.push_back(tmp);
        while (!q.empty()) {
            size = q.size();
            while (size --) {
                tmp = q.front();
                q.pop_front();
                if (tmp.x == (m-1) && tmp.y == (n -1)) {   // 已经到达终点,直接跳出
                    flag = 1;
                    break;
                }
                for (i = 0 ; i < 4; i++) {         // 将周围合适的点存入
                    if (can_vis(tmp.x + mov[i][0], tmp.y + mov[i][1], tmp.p) == true) {
                        tmp1.x = tmp.x + mov[i][0];
                        tmp1.y = tmp.y + mov[i][1];
                        tmp1.p = tmp.p;
                        visited[tmp1.x][tmp1.y][tmp1.p] = true;
                        q.push_back(tmp1);
                    }
                }
                for (i = 0; i < 4; i++) {               // 查找能飞的区域
                    for (j = 0; j <= tmp.p; j++) {
                        tmp1.x = tmp.x + mov[i][0] * j;
                        tmp1.y = tmp.y + mov[i][1] * j;
                        tmp1.p = tmp.p - j;
                        if (can_vis(tmp1.x, tmp1.y, tmp1.p) == true) {
                            visited[tmp1.x][tmp1.y][tmp1.p] = true;
                            q.push_back(tmp1);
                        }
                    }
                }
            }
            if (flag == 1) break;
            result ++;
        }
        if (flag == 1) cout << result << endl;
        else cout << "impossible" << endl;
        
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章