程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> hdu1429之BFS

hdu1429之BFS

編輯:C++入門知識

勝利大逃亡(續)
Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3778    Accepted Submission(s): 1236


Problem Description
Ignatius再次被魔王抓走了(搞不懂他咋這麼討魔王喜歡)……

這次魔王汲取了上次的教訓,把Ignatius關在一個n*m的地牢裡,並在地牢的某些地方安裝了帶鎖的門,鑰匙藏在地牢另外的某些地方。剛開始Ignatius被關在(sx,sy)的位置,離開地牢的門在(ex,ey)的位置。Ignatius每分鐘只能從一個坐標走到相鄰四個坐標中的其中一個。魔王每t分鐘回地牢視察一次,若發現Ignatius不在原位置便把他拎回去。經過若干次的嘗試,Ignatius已畫出整個地牢的地圖。現在請你幫他計算能否再次成功逃亡。只要在魔王下次視察之前走到出口就算離開地牢,如果魔王回來的時候剛好走到出口或還未到出口都算逃亡失敗。

 

Input
每組測試數據的第一行有三個整數n,m,t(2<=n,m<=20,t>0)。接下來的n行m列為地牢的地圖,其中包括:

. 代表路
* 代表牆
@ 代表Ignatius的起始位置
^ 代表地牢的出口
A-J 代表帶鎖的門,對應的鑰匙分別為a-j
a-j 代表鑰匙,對應的門分別為A-J

每組測試數據之間有一個空行。

 

Output
針對每組測試數據,如果可以成功逃亡,請輸出需要多少分鐘才能離開,如果不能則輸出-1。

 

Sample Input
4 5 17
@A.B.
a*.*.
*..*^
c..b*

4 5 16
@A.B.
a*.*.
*..*^
c..b*

Sample Output
16
-1

 

分析:根據提議可知每到一個點[i,j]有兩個狀態,1是時間,2是鑰匙數,而本題判斷是否以前到達點{I,j]需要用到狀態2,因為同一個點到達的方式可能鑰匙數不一樣,從而導致後面能走得路不一樣,時間就不用標記,用廣搜肯定是同樣狀態裡面的最短時間,所以用mark[i][j][key]標記到達i,j鑰匙為key的狀態

另外可以發現本題鑰匙種類最多10個(a~j),則可以用數位表示,即1111111111表示10個鑰匙都有,1111111110表示第一個鑰匙沒有......0000000000表示沒有鑰匙

 

#include<iostream>   
#include<cstdio>   
#include<cstdlib>   
#include<cstring>   
#include<string>   
#include<algorithm>   
#include<queue>   
#include<map>   
#include<iomanip>   
#define INF 99999999   
using namespace std;  
  
const int MAX=20+10;  
char Map[MAX][MAX];  
int n,m,t;  
int mark[MAX][MAX][1<<11];//1<<1表示在i,j點獲得x種的鑰匙是否已走過   
int dir[4][2]={0,1,0,-1,1,0,-1,0};  
  
struct Node{  
    int x,y,time,key;//在x,y點的時間和獲得的鑰匙    
    Node(){}  
    Node(int X,int Y,int Time,int Key):x(X),y(Y),time(Time),key(Key){}  
}start;  
  
int BFS(int &flag){  
    mark[start.x][start.y][start.key]=flag;  
    queue<Node>q;  
    Node next,oq;  
    q.push(start);  
    while(!q.empty()){  
        oq=q.front();  
        q.pop();  
        for(int i=0;i<4;++i){  
            next=Node(oq.x+dir[i][0],oq.y+dir[i][1],oq.time+1,oq.key);  
            if(next.x<0 || next.y<0 || next.x>=n || next.y>=m)continue;  
            if(mark[next.x][next.y][next.key] == flag || Map[next.x][next.y] == '*')continue;  
            mark[next.x][next.y][next.key]=flag;  
            if(next.time>=t)return -1;  
            if(Map[next.x][next.y] == '^')return next.time;  
            if(Map[next.x][next.y]>='A' && Map[next.x][next.y]<='Z'){  
                int k=Map[next.x][next.y]-'A';  
                if(next.key & (1<<k))q.push(next);//表示有這個鑰匙A~J分別對應key裡的第1~10位   
                continue;  
            }  
            if(Map[next.x][next.y]>='a' && Map[next.x][next.y]<='z'){  
                int k=Map[next.x][next.y]-'a';  
                next.key=next.key | (1<<k);  
            }  
            q.push(next);  
        }  
    }  
    return -1;  
}  
  
int main(){  
    int num=0;  
    while(cin>>n>>m>>t){  
        for(int i=0;i<n;++i)cin>>Map[i];  
        for(int i=0;i<n;++i){  
            for(int j=0;j<m;++j){  
                if(Map[i][j] == '@'){start.x=i,start.y=j;start.time=start.key=0;}  
            }  
        }  
        cout<<BFS(++num)<<endl;  
    }  
    return 0;  
}   

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved