HDU 4845 拯救大兵瑞恩 基本状态压缩bfs

来源:互联网 发布:成都大旗软件 编辑:程序博客网 时间:2024/04/28 10:59

题意:1944年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。瑞恩被关押在一个迷宫里,迷宫地形复杂,但是幸好麦克得到了迷宫的地形图。
   迷宫的外形是一个长方形,其在南北方向被划分为N行,在东西方向被划分为M列,于是整个迷宫被划分为N*M个单元。我们用一个有序数对(单元的行号,单元的列号)来表示单元位置。南北或东西方向相邻的两个单元之间可以互通,或者存在一扇锁着的门,又或者存在一堵不可逾越的墙。迷宫中有一些单元存放着钥匙,并且所有的门被分为P类,打开同一类的门的钥匙相同,打开不同类的门的钥匙不同。
   大兵瑞恩被关押在迷宫的东南角,即(N,M)单元里,并已经昏迷。迷宫只有一个入口,在西北角,也就是说,麦克可以直接进入(1,1)单元。另外,麦克从一个单元移动到另一个相邻单元的时间为1,拿取所在单元的钥匙的时间以及用钥匙开门的时间忽略不计。
   你的任务是帮助麦克以最快的方式抵达瑞恩所在单元,营救大兵瑞恩。


想法:典型的状态压缩,把麦克的位置和身上钥匙可以开的门记录下来,然后有一个地方就是,一个地点可能会有多把钥匙,这个要想到。然后把可以开那些门用二进制的1表示就好了,应为最多也就10个门。


#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;const int nodes=15;int n,m,p;bool wall[nodes][nodes][nodes][nodes];int door[nodes][nodes][nodes][nodes];int key[nodes][nodes];bool vis[1<<12][nodes][nodes];int dir[4][2]={1,0,0,1,0,-1,-1,0};struct node{    int x,y;    int sta;    int tim;};void init(){    memset(wall,false,sizeof(wall));    memset(door,0,sizeof(door));    memset(key,0,sizeof(key));}void bfs(){    memset(vis,false,sizeof(vis));    node head,nxt;    queue<node>q;    while(!q.empty()) q.pop();    head.x=1;head.y=1;head.sta=0;head.tim=0;    if(key[1][1])    {        head.sta|=key[1][1];    }    q.push(head);    vis[head.sta][1][1]=true;    while(!q.empty())    {        head=q.front();        q.pop();        if(head.x==n&&head.y==m)        {            printf("%d\n",head.tim);            return;        }        for(int i=0;i<4;i++)        {            nxt.x=head.x+dir[i][0];            nxt.y=head.y+dir[i][1];            nxt.tim=head.tim+1;            nxt.sta=head.sta;            if(wall[head.x][head.y][nxt.x][nxt.y]) continue;            if(nxt.x<1||nxt.x>n||nxt.y<1||nxt.y>m) continue;            int dn=door[head.x][head.y][nxt.x][nxt.y];            if(dn)            {                if(!(1<<(dn-1)&nxt.sta)) continue;            }            if(key[nxt.x][nxt.y])            {                nxt.sta|=key[nxt.x][nxt.y];            }            if(!vis[nxt.sta][nxt.x][nxt.y])            {                vis[nxt.sta][nxt.x][nxt.y]=true;                q.push(nxt);            }        }    }    printf("-1\n");    return;}int main(){    while(~scanf("%d%d%d",&n,&m,&p))    {        init();        int K;        scanf("%d",&K);        for(int i=1;i<=K;i++)        {            int x1,y1,x2,y2,g;            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&g);            if(!g) wall[x1][y1][x2][y2]=wall[x2][y2][x1][y1]=true;            else door[x1][y1][x2][y2]=door[x2][y2][x1][y1]=g;        }        int S;        scanf("%d",&S);        for(int i=1;i<=S;i++)        {            int x,y,z;            scanf("%d%d%d",&x,&y,&z);            key[x][y]|=1<<(z-1);        }        bfs();    }    return 0;}



0 0