hdu 4845 : 拯救大兵瑞恩 (bfs+状态压缩)

 题目链接

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

int n,m,p,s,k;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};

bool vis[16][16][1<<11];    //vis[i][j][k]记录是否以k状态访问过(i,j)位置 
int wall[16][16][16][16];    //记录墙和门的情况 
int key[16][16];            //记录迷宫中钥匙的存在状态 

struct node
{
    int x,y;        //x,y记录坐标 
    int own;        //own记录钥匙的拥有情况 
    int dis;        //dis记录到原点的最短距离 
};

bool in(int x,int y)
{
    return 1<=x&&x<=n&&1<=y&&y<=m;
}

int bfs()
{
    vis[1][1][key[1][1]]=1;
    queue<node> q;
    q.push((node){1,1,key[1][1],0});
    while(!q.empty())
    {
        node cur=q.front();
        q.pop();
        int px=cur.x,py=cur.y,pdis=cur.dis;
        for(int i=0;i<4;i++)
        {
            int own=cur.own;
            int x=px+dx[i];
            int y=py+dy[i];
            if(!in(x,y)||wall[px][py][x][y]==0) continue;    //不在边界内或是一堵墙 
            int door= (wall[px][py][x][y]==-1? 0:wall[px][py][x][y]);
            if(!(own&(1<<door)))    continue;    //没有钥匙 
            if(x==n&&y==m) return pdis+1;        //到达终点 
            own|=key[x][y];        //捡到该点的钥匙 
            if(vis[x][y][own])    continue;
            vis[x][y][own]=1; 
            q.push((node){x,y,own,pdis+1});
        }
    }
    return -1;
}

int main()
{
    while(cin>>n>>m>>p)
    {
        memset(wall,-1,sizeof(wall));
        memset(key,0,sizeof(key));
        memset(vis,0,sizeof(vis));
        cin>>k;
        while(k--)
        {
            int x1,y1,x2,y2,g;
            cin>>x1>>y1>>x2>>y2>>g;
            wall[x1][y1][x2][y2]=wall[x2][y2][x1][y1]=g;
        }
        cin>>s;
        while(s--)
        {
            int x,y,q;
            cin>>x>>y>>q;
            key[x][y]|=1<<q;
        }
        key[1][1]|=1;    //捡到原点的钥匙 
        cout<<bfs()<<endl;
    }
}
原文地址:https://www.cnblogs.com/Just--Do--It/p/7307717.html