1. 程式人生 > >1429 勝利大逃亡(續)

1429 勝利大逃亡(續)

相關演算法:廣度優先搜尋(百度連結)

#include <iostream>
#include <queue>
using namespace
std;

int
dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};    //移動路徑表
int m,n,t;
char
map[22][22];                            //地圖

struct
node{                                //點狀態

    short x,y;
    short
key;
    short
step;
}
start,now,temp;

int

transch_2(char in, int key){    //檢查是否需要撿起鑰匙,需要撿起返回對應的整數,已經擁有該鑰匙返回0
    int t = 1<<(int)(in-'a');        //鑰匙對應的整數值
    return (key & t) ? 0 : t;        //檢查是否已經擁有鑰匙
}

bool
chkkey(char in, int key){        //檢查是否能開啟該門
    return (key>>(int)(in-'A'))&1;
}


void
read(){                        //讀取地圖
    int
i,j;
    for
(i=1; i<=m; i++)            //畫頂行牆
        map[0][i] = '*';           
    for
(i=1; i<=n; i++){
        getchar();                    //迴避回車字元
        map[i][0] = '*';
        for
(j=1; j<=m; j++){
            map[i][j] = getchar();
            if
(map[i][j] == '@'){    //檢查是否為起點
                start.
x = i;
                start.y = j;
            }
        }

        map[i][m+1] = '*';
    }

    for
(i=1; i<=m; i++)            //畫底行牆
        map[n+1][i] = '*';
    start.key = 0;                    //初始化start點
    start.step = 0;
}


int
DPS(){                                    //廣優演算法
    queue<node>q;
    int
x,y,step,key;                        //臨時狀態
    char tp;                                //當前點的字元號
    bool visited[22][22][1024]={false};        //儲存訪問狀態[x][y][鑰匙狀態]
    q.push(start);                            //起始點入列
    visited[start.x][start.y][0] = true;    //標記起點
    while (!q.empty()){
        now = q.front();
        q.pop();
        step=now.step+1;                    //時間計算
        if (step==t)                        //超時判斷
            break;
        for
(int i=0; i<4; i++){
            x=now.x+dir[i][0];
            y=now.y+dir[i][1];
            key=now.key;
            tp = map[x][y];
            if
(!(tp == '*' || visited[x][y][key])){    //判斷是否為牆壁,是否走過
                if (tp >= 'A' && tp <='J'){
                    if
(!chkkey(tp,key))                //判斷是否持有對應鑰匙
                        continue;                        //了結該點,執行下一次迴圈
                }else if(tp >= 'a' && tp <='j'){
                    key += transch_2(tp,key);            //取得鑰匙
                }else if(tp == '^'){
                    return
step;                        //到達出口,返回使用時間
                }
                temp.x=x;
                temp.y=y;
                temp.step=step;
                temp.key=key;
                q.push(temp);                            //該步可走,進入佇列
                visited[x][y][key] = true;                //當前位置標記為已走過
            }
        }
    }

    return
-1; //無法逃亡,返回-1 }

int
main(int argc, char* argv[]){
    while
(scanf("%d%d%d",&n,&m,&t) != EOF){
        read();
        printf("%d/n",DPS());
    }

    return
0;
}