深夜补题...
【Description】
你所在的迷宫可以用 N 行 M 列的矩阵来描述:
图标 含义
# 墙,无法通过
. 地面,可以通过
小写字母(a、b、c、...、z) 钥匙,可以打开标有对应大写字母的门
大写字母(A、B、C、...、Z) 门,可以被标有对应小写字母的钥匙打开
$ 你的初始位置
& 迷宫的出口位置
迷宫的四周都有墙,所以你无法走出这片 N*M 的区域,只能从”&”处离开迷宫,你只能
向东西南北四个方向走。
你的任务是,计算出走出迷宫需要的最少步数是多少?
【Input】
第 1 行两个正整数 N 和 M,表示迷宫的长和宽;
第 2 行一个正整数 P,表示门和钥匙的数量;
第 3 行至第 N+2 行,描述整个迷宫。
【Output】
一个整数,为走出迷宫需要的最少步数或-1(如果不可能走出迷宫)。
#include <cstdio> #include <queue> #include <climits> #include <ctype.h> #define pname "maze2" #define commonfio freopen(pname".in","r",stdin); freopen(pname".out","w",stdout); char mp[105][105]; using namespace std; #define pushnode(x,y,k) q.push(x); q.push(y); q.push(k) #define popnode(x,y,k) x=q.front(); q.pop();y=q.front(); q.pop();k=q.front(); q.pop() #define toc mp[nx][ny] queue<int> q; bool vis[105][105][1<<10]; int dis[105][105][1<<10]; int dx[]= {-1,0,0,1}; int dy[]= {0,1,-1,0}; #define has(n) (s&(1<<n)) #define clr(id) ns=ns&(~(1<<id)) #define set(id) ns=ns|(1<<id) int n,m,p; int main() { int sx,sy,ex,ey; commonfio; scanf("%d%d%d", &n, &m, &p); for (int i=1; i<=n; i++) { scanf("%s",mp[i]+1); } for (int i=1; i <= n; i++) for (int j = 1; j <= m; j++) if (mp[i][j] == ‘$‘) { sx = i; sy = j; } for (int i=1; i <= n; i++) for (int j = 1; j <= m; j++) if (mp[i][j] == ‘&‘) { ex = i; ey = j; } pushnode(sx,sy,0); vis[sx][sy][0]=1; while(!q.empty()) { int x,y,s; popnode(x,y,s); // printf("%d %d %d\n",x,y,s); vis[x][y][s]=0; for(int i=0; i<4; i++) { int nx=x+dx[i],ny=y+dy[i],ns=s; if (nx < 1 || ny < 1 || nx > n || ny > m) continue; char cc=toc; if(cc==‘#‘) continue; if(cc!=‘.‘ && cc!=‘&‘ && cc!=‘$‘) { if(isupper(cc)) { int id=cc-‘A‘; if(has(id)==0) continue; //clr(id); } else { int id=cc-‘a‘; set(id); } } if(dis[x][y][s]+1<dis[nx][ny][ns] || dis[nx][ny][ns]==0) { dis[nx][ny][ns]=dis[x][y][s]+1; if(!vis[nx][ny][ns]) { vis[nx][ny][ns]=1; pushnode(nx,ny,ns); } } } } int ans=INT_MAX; for (int i = 0; i < (1 << p); i++) { if(dis[ex][ey][i]!=0 && ans>dis[ex][ey][i] ) ans=dis[ex][ey][i]; } printf("%d\n",ans==INT_MAX?-1:ans); }
时间: 2024-10-13 18:17:32