题意: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; }