版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GYH0730/article/details/82390197
题目链接:https://www.luogu.org/recordnew/show/10464387
【问题分析】
分层图最短路径问题。
【建模方法】
用P位二进制表示当前获得的钥匙状态,建立2^P层图。每层图表示在当前钥匙状态下的地图,每获得一把钥匙进入新的一层,BFS求最短路即可。
明明就是状压+BFS为什么会出现在网络流24题里???
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
struct node
{
int step,x,y,state;
//分别记录格子的坐标,步数,有哪些钥匙
node(){}
node(int _x,int _y,int _step,int _state)
{
x = _x,y = _y;
step = _step,state = _state;
}
};
int n,m,p;
int mp[51][51][51][51];//记录地图信息
int to[4][2] = {1,0,0,1,-1,0,0,-1};
int key[51][51];//每一个格子的钥匙有哪些
bool vis[51][51][1 << 10];//标记格子状态,避免重复访问
bool judge(int x,int y)
{
if(x <= 0 || y <= 0 || x > n || y > m) {
return 0;
}
return 1;
}
void BFS()
{
struct node now,next;
memset(vis,0,sizeof(vis));
queue<node> q;
q.push(node(1,1,0,key[1][1]));
vis[1][1][key[1][1]] = 1;
while(!q.empty()) {
now = q.front();
q.pop();
for(int i = 0; i < 4; i++) {
next.x = now.x + to[i][0];
next.y = now.y + to[i][1];
next.state = now.state | key[next.x][next.y];
next.step = now.step + 1;
if(!judge(next.x,next.y)) continue;
//格子的状态是否被访问过
if(vis[next.x][next.y][next.state]) continue;
int ty = mp[now.x][now.y][next.x][next.y];
//是否为墙
if(ty == 0) continue;
//是否有门的钥匙
if(ty > 0 && !((next.state >> (ty - 1)) & 1)) continue;
vis[next.x][next.y][next.state] = 1;
if(next.x == n && next.y == m) {
printf("%d\n",next.step);
return;
}
q.push(next);
}
}
printf("-1\n");
}
int main(void)
{
int x1,y1,x2,y2,ty;
int num;
while(scanf("%d%d%d",&n,&m,&p) != EOF) {
memset(mp,-1,sizeof(mp));
memset(key,0,sizeof(key));
scanf("%d",&num);
while(num--) {
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&ty);
mp[x1][y1][x2][y2] = ty;
mp[x2][y2][x1][y1] = ty;
}
scanf("%d",&num);
while(num--) {
scanf("%d%d%d",&x1,&y1,&ty);
key[x1][y1] |= (1 << (ty - 1));
}
BFS();
}
return 0;
}