SDUTOJ 2193救基友記3

題目描述

  話說CZ由於不守基道,被妖怪抓走了,好基友WP在努力討好高富帥RQ救出CZ的同時,CZ也意識到了自己的錯誤,然後努力的想逃出妖怪的閨房。 
   妖怪的閨房是一個n*m的矩陣,並且某些地方安裝了帶鎖的門,鑰匙藏在閨房另外的某些地方。剛開始WP被關在(sx,sy)的位置,離開閨房的門在(ex,ey)的位置。WP每分鐘只能從一個座標走到相鄰四個座標中的其中一個。妖怪每t分鐘回閨房視察一次,若發現CZ不在原位置便把他再拎回去。經過若干次的嘗試,CZ已畫出整個閨房的地圖。現在請你幫他計算能否再次成功逃亡。只要在妖怪下次視察之前走到出口就算離開閨房,如果妖怪回來的時候剛好走到出口或還未到出口都算逃亡失敗。

輸入

 每組測試數據的第一行有三個整數n,m,t(2<=n,m<=20,t>0)。接下來的nm列爲閨房的地圖,其中包括:
代表路
代表牆
代表CZ的起始位置
代表閨房的出口
A-J 代表帶鎖的門,對應的鑰匙分別爲a-j
a-j 代表鑰匙,對應的門分別爲A-J

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

輸出

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

示例輸入

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

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

示例輸出

16
-1


本題的難點是在於鑰匙的狀態。上網查閱一番才知道用2進制的表示方法,頓時茅塞頓開,同時感覺智商已被深深壓制。故在此解釋一下2進制的用法。
本題鑰匙用a~j表示,門用A~J表示則將其表示爲2進制只需對相應字符減一個‘a’或‘A’,再以此循環乘2。把結果加到儲存狀態的變量上,這樣雖然是一個數,但它寫成2進制是就可以變成0000000,1111111這樣的數。如果第一位是0,則表示沒有鑰匙a,如果是一則擁有a,同理第二位表示b。。。。這樣做高明就高明在用一個數就能表示多種狀態,是在佩服那些大神的智慧啊。
本題代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct B
{
    int x,y,z;
    int step;
} p[1000001],q,f;
char map[22][22];
int vis[22][22][1101];
int mov[4][2]= {{1,0},{-1,0},{0,1},{0,-1}};
int n,m,t;
void bfs(int x,int y)
{
    int top=0,low=0;
    int i,flag=0;
    q.x=x;
    q.y=y;
    q.z=0;
    q.step=0;
    vis[q.x][q.y][0]=1;
    p[top++]=q;
    while(low<top)
    {
        q=p[low++];
        if(map[q.x][q.y]=='^')
        {
                if(q.step<t){printf("%d\n",q.step);flag=1;}
                break;
        }
        for(i=0; i<4; i++)
        {
            f.x=q.x+mov[i][0];
            f.y=q.y+mov[i][1];
            f.z=q.z;
            if(0<=f.x&&f.x<n&&0<=f.y&&f.y<m&&
               vis[f.x][f.y][f.z]==0&&map[f.x][f.y]!='*')
            {
                if(map[f.x][f.y]=='^'||map[f.x][f.y]=='.'||
                        map[f.x][f.y]=='@')
                {
                    f.step=q.step+1;
                    p[top++]=f;
                    vis[f.x][f.y][f.z]=1;
                }
                else
                {
                    if('a'<=map[f.x][f.y]&&map[f.x][f.y]<='j')
                    {
                        int ll=map[f.x][f.y]-'a',kk=f.z,sum;\\儲存鑰匙狀態
                        while(ll--)
                        {
                            kk=kk/2;
                        }
                        sum=kk%2;
                        if(sum==0)
                        {
                            ll=map[f.x][f.y]-'a';
                            kk=1;
                            while(ll--)
                            {
                                kk=kk*2;
                            }
                            f.z=f.z+kk;
                        }
                        f.step=q.step+1;
                        p[top++]=f;
                        vis[f.x][f.y][f.z]=1;
                    }
                    else
                    {
                        if(map[f.x][f.y]>='A'&&map[f.x][f.y]<='J')\\判斷鑰匙是否存在
                        {
                            int ll=map[f.x][f.y]-'A',kk=f.z,sum;
                            while(ll--)
                            {
                                kk=kk/2;
                            }
                            sum=kk%2;
                            if(sum==1)
                            {
                                f.step=q.step+1;
                                p[top++]=f;
                                vis[f.x][f.y][f.z]=1;
                            }
                        }
                    }
                }
            }
        }
    }
    if(flag==0)
    printf("-1\n");
    return ;
}
int main()
{
    int i,j;
    while(scanf("%d %d %d",&n,&m,&t)!=EOF)
    {
        for(i=0; i<n; i++)
        {
            scanf("%*c%s",map[i]);
        }
        for(i=0; i<n; i++)
        {
            for(j=0; j<m; j++)
            {
                if(map[i][j]=='@')break;
            }
            if(j!=m)break;
        }
        memset(vis,0,sizeof(vis));
        bfs(i,j);
    }
    return 0;
}










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