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;
}


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