1. 程式人生 > >2018年 ICPC北京網路預選賽 A題 Saving Tang Monk II

2018年 ICPC北京網路預選賽 A題 Saving Tang Monk II

由於個人比較菜啊,這道題錯了4次才ac,思路是對的,就是各種死在細節上。

題目大意:唐僧給妖精抓走了,悟空要去救出唐僧,給你一個地圖長N高M,‘S’表示悟空所在地,‘T’ 表示唐僧所在地,‘.’i表示空地,‘B’表示氧氣罐補給室,氧氣罐補給室有無限的氧氣罐,但悟空每次到達氧氣罐補給室可以拿走一個氧氣罐,最多拿5個,P表示加速藥丸,也是每個P房間有無限個加速藥丸,但是每次到達只能買一個(悟空不可以原地踏步),‘#’代表毒氣室,如果悟空沒有氧氣罐則無法進入毒氣室,每次進入毒氣室需要消耗一個氧氣罐。

悟空每次進入一個房間要消耗一分鐘,經過毒氣室要額外消耗一分鐘,加速藥丸可以加速一分鐘的行動,使其不需要時間可以完成,一個加速藥丸只可以使用一次。

思路:很簡單嘛,一看看過去就是廣搜,但是要優化,用一個v[105][105][6]三位陣列儲存狀態,儲存到某一個位置,有N個氧氣罐的時候需要的步伐,如果下次到達某處時,目前擁有的氧氣罐和上次到達這裡的氧氣罐數相同且步數小於時才繼續走。

我程式碼寫的比較繁瑣,但是可以可讀性應該還行。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
char d[105][105];
struct poi
{
    int x,y,v;
}fin,p;
int w[4]={1,-1,0,0};
int ad[4]={0,0,1,-1};
long long v[105][105][6];
int m,n;
void bfs()
{
    queue<poi> que;
    p.v=0;
    que.push(p);
    poi pp;
    while(!que.empty())
    {
        p=que.front();
        que.pop();
        for(int i=0;i<4;i++)
        {
            if(p.x+ad[i]>=0&&p.x+ad[i]<n&&p.y+w[i]>=0&&p.y+w[i]<m)//判斷要移動到的位置是否超過邊界
            {
                if(d[p.y+w[i]][p.x+ad[i]]=='#')//下一個是#
                {
                    if(p.v-1>=0&&(v[p.y+w[i]][p.x+ad[i]][p.v-1]==-1||v[p.y][p.x][p.v]+2<v[p.y+w[i]][p.x+ad[i]][p.v-1]))
                    {
                        v[p.y+w[i]][p.x+ad[i]][p.v-1]=v[p.y][p.x][p.v]+2;
                        pp.x=p.x+ad[i];
                        pp.y=p.y+w[i];
                        pp.v=p.v-1;
                        que.push(pp);
                    }
                }
                else if(d[p.y+w[i]][p.x+ad[i]]=='P')//下一個是P
                {
                    if(v[p.y][p.x][p.v]<v[p.y+w[i]][p.x+ad[i]][p.v]||v[p.y+w[i]][p.x+ad[i]][p.v]==-1)
                    {
                        v[p.y+w[i]][p.x+ad[i]][p.v]=v[p.y][p.x][p.v];
                        pp.x=p.x+ad[i];
                        pp.y=p.y+w[i];
                        pp.v=p.v;
                        que.push(pp);
                    }
                }
                else if(d[p.y+w[i]][p.x+ad[i]]=='.')//下一個是.
                {
                    if(v[p.y][p.x][p.v]+1<v[p.y+w[i]][p.x+ad[i]][p.v]||v[p.y+w[i]][p.x+ad[i]][p.v]==-1)
                    {
                        v[p.y+w[i]][p.x+ad[i]][p.v]=v[p.y][p.x][p.v]+1;
                        pp.x=p.x+ad[i];
                        pp.y=p.y+w[i];
                        pp.v=p.v;
                        que.push(pp);
                    }
                }
                else if(d[p.y+w[i]][p.x+ad[i]]=='T')//終點
                {
                    if(v[p.y][p.x][p.v]+1<v[p.y+w[i]][p.x+ad[i]][p.v]||v[p.y+w[i]][p.x+ad[i]][p.v]==-1)
                    {
                        v[p.y+w[i]][p.x+ad[i]][p.v]=v[p.y][p.x][p.v]+1;
                    }
                }
                else if(d[p.y+w[i]][p.x+ad[i]]=='B')//下一個點是B
                {
                    if(p.v+1<=5)//充氣
                    {
                        if(v[p.y][p.x][p.v]+1<v[p.y+w[i]][p.x+ad[i]][p.v+1]||v[p.y+w[i]][p.x+ad[i]][p.v+1]==-1)
                        {
                            v[p.y+w[i]][p.x+ad[i]][p.v+1]=v[p.y][p.x][p.v]+1;
                            pp.x=p.x+ad[i];
                            pp.y=p.y+w[i];

                            que.push(pp);
                        }
                    }
                    else//不充氣
                    {
                    if(v[p.y][p.x][p.v]+1<v[p.y+w[i]][p.x+ad[i]][p.v]||v[p.y+w[i]][p.x+ad[i]][p.v]==-1)
                        {
                            v[p.y+w[i]][p.x+ad[i]][p.v]=v[p.y][p.x][p.v]+1;
                            pp.x=p.x+ad[i];
                            pp.y=p.y+w[i];
                            pp.v=p.v;
                            que.push(pp);
                        }
                    }

                }
            }
        }
    }
}
int main(int argc, char *argv[])
{
    while(scanf("%d %d",&m,&n)!=EOF&&(m!=0||n!=0))
    {
        memset(v,-1,sizeof(v));
        p.x=0;
        p.y=0;
        fin.x=0;
        fin.y=0;
        for(int i=0;i<m;i++)
        {
            scanf("%s",d[i]);
            for(int j=0;j<n;j++)
            {
                if(d[i][j]=='T')
                {
                    fin.x=j;
                    fin.y=i;
                }
                else if(d[i][j]=='S')
                {
                    p.x=j;
                    p.y=i;
                    d[i][j]='.';//轉化成.方便等下判斷
                    v[i][j][0]=0;
                }
            }
        }
        bfs();
        int f=0;
        long long ma=-1;
        for(int i=0;i<=5;i++)//如果全都是-1則表示悟空無法到達
        {
            if(!f&&v[fin.y][fin.x][i]!=-1)
            {
                ma=v[fin.y][fin.x][i];
                f=1;
            }
            else if(ma>v[fin.y][fin.x][i]&&v[fin.y][fin.x][i]!=-1)
                ma=v[fin.y][fin.x][i];
        }
        if(ma==-1)
            ma=-1;
        printf("%lld\n",ma);
    }
    return 0;
}