1131. 拯救大兵瑞恩

解题思路:题目大意是要到一个位置,但是图中会有对应的门,而且门的种类不同,需要不同种钥匙来打开,不同种的钥匙分别放在地图中的某个位置,问最多要多少步才能到。
这道题的解题思路也是非常的取巧,他并没有告诉你每个点之间的边,这个需要我们去构造,并且还有墙,墙是不可逾越的,那么我们需要用一个set来维护两条边之间是否存在墙或者门,我们初始的dist一维数组是肯定不够的,要开第二个状态[j],这里的状态应该用个二进制状态来存,如果开始搜的时候两点之间的w[i]如果大于0,那么二进制状态右移w[i]位&1如果等于0那么就不存在。在采用bfs的时候,如果脚下有钥匙我们肯定要捡起,然后双端队列的可以做到优化的效果,把捡钥匙的放在队头,不捡的放在队尾。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<deque>
#include<set>
using namespace std;
const   int N = 11 ,M=N*N*4 ,P = 1<<10;
#define x first
#define y second
typedef pair<int ,int> PII;
set<PII>S;
int e[M],ne[M],h[M],w[M];
int dist[M][P];
bool st[M][P];
int g[N][N];
int key[M];
int idx ;
int n , m , p ,s , k ;
void add(int a,int b,int c)
{
   
    e[idx] =  b, w[idx] = c ,ne[idx] = h[a], h[a] = idx++; 
}
void build()
{
   
    int dx[4] ={
   1,-1,0,0},dy[4]={
   0,0,1,-1};
    for(int i=1; i<=n;i++)
    for(int j = 1;j<=m;j++)
    for(int k=0;k<4;k++)
    {
   
        int tx=i+dx[k];
        int  ty=j+dy[k];
        if(!tx||!ty||tx>n||ty>m)    continue;
        if(S.count({
   g[tx][ty],g[i][j]}))    continue;
        add(g[tx][ty],g[i][j],0),add(g[i][j],g[tx][ty],0);
    }
}
int bfs()
{
   
    deque<PII>q;
    memset(dist,0x3f,sizeof dist);
    dist[1][0]=0;
    st[1][0]=true;
    q.push_back({
   1,0});
    while(q.size())
    {
   
        PII t= q.front();
        q.pop_front();
        if(t.x==n*m)
        return dist[t.x][t.y];
        if(key[t.x])
        {
   
            int ss =t.y|key[t.x];
            if(dist[t.x][ss]>dist[t.x][t.y])
            {
   
                dist[t.x][ss]=dist[t.x][t.y];
                st[t.x][ss]=true;
                q.push_front({
   t.x,ss});
            }
        }
        for(int i=h[t.x];~i;i=ne[i])
        {
   
            int j=e[i];
            if(w[i]&&!(t.y>>w[i]-1&1))  continue;
            if(dist[j][t.y]>dist[t.x][t.y]+1)
            {
   
                dist[j][t.y]=dist[t.x][t.y] +1;
                if(!st[j][t.y])
            {
   
                st[j][t.y]=true;
                q.push_back({
   j,t.y});
            }
            }
        }
    }
    return -1;
}
int main()
{
   
    memset(h,-1,sizeof h);
    cin >>  n >> m >> p >> k;
    for(int i = 1,t=1 ;i <= n   ; i++)
    for(int j = 1; j<= m; j++)
    g[i][j] =  t++;
    while(k--)
    {
   
        int x1 ,y1, x2 ,y2 ,G;
        cin >> x1 >> y1 >> x2 >> y2 >> G;
        int a = g[x1][y1] , b =  g[x2][y2];
        if(G)   add(a,b,G),add(b,a,G);
        S.insert({
   a,b}),S.insert({
   b,a});
    }
    build();
    cin >>  s;
    while(s--)
    {
   
        int x1,y1,t;
        cin >> x1 >> y1 >> t;
        int loc = g[x1][y1];
        key[loc] |= 1<< t -1 ;
    }
    cout << bfs() << endl;
    return 0;
}
全部评论

相关推荐

评论
点赞
收藏
分享
牛客网
牛客企业服务