题目链接:https://loj.ac/problem/6121
题意:
给你一个n*m的图,你要从(1,1)出发到达(n,m),路上会有最多p种墙和钥匙。接下来会给你k个门,在x1,y1,x2,y2之间会有一扇ki类型的门,如果ki为0,那么无法穿过,否则你要拿到对应ki的钥匙才可以穿过,同理接下来会有s把钥匙,这些钥匙在xi,yi处,类型为ki。,每走一步需要1的时间,现在问你从起点到终点最少需要多少时间。
做法:
好像做到过很多次了这种题目,因为题目的数据范围很小,所以不需要太多的优化,直接做就好了,只是最短路在处理的时候加上一个状态这个量就好了,因为钥匙和门的对应种类最多只有10,完全可以状压成状态,01代表这个钥匙是否被拿过,dp这个的时候也要加上状态的量,然后用优先队列减少宽搜时间,到达之后就可以直接break掉。
不过这题有个坑点,就是一个格子种可能会有多把钥匙,没看清这个条件wa了好几次。难受巴巴。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int n,m,p,mp[150][150],k,dp[15][15][4000],key[15][15],ans;
struct node{
int x,y,step,state;
node(){}
node(int x,int y,int step,int state):x(x),y(y),step(step),state(state){}
bool operator < (const node &a) const {
return step>a.step;
}
};
int gain(int x,int y){
return m*(x-1)+y;
}
int ck(int state,int x,int y,int tx,int ty){
int a=gain(x,y),b=gain(tx,ty);
if(x<1||x>n||y<1||y>m||mp[a][b]==0) return 0;
if(mp[a][b]==-1) return 1;
else {
int now=mp[a][b];
if(state&(1<<(now-1))) return 1;
return 0;
}
}
void bfs(){
priority_queue<node> q;
dp[1][1][0]=0;
q.push(node(1,1,0,0));
while(!q.empty()){
node u=q.top(); q.pop();
if(u.x==n&&u.y==m){
ans=u.step;
break;
}
for(int i=0;i<4;i++){
int dx=u.x+dir[i][0],dy=u.y+dir[i][1];
if(ck(u.state,dx,dy,u.x,u.y)){
if(key[dx][dy]!=-1){
int now=key[dx][dy];
int nextstate=u.state|now;
if(dp[dx][dy][nextstate]>dp[u.x][u.y][u.state]+1){
dp[dx][dy][nextstate]=dp[u.x][u.y][u.state]+1;
q.push(node(dx,dy,u.step+1,nextstate));
}
}
else {
if(dp[dx][dy][u.state]>dp[u.x][u.y][u.state]+1){
dp[dx][dy][u.state]=dp[u.x][u.y][u.state]+1;
q.push(node(dx,dy,u.step+1,u.state));
}
}
}
}
}
}
int main(){
ans=-1;
memset(dp,125,sizeof(dp));
memset(mp,-1,sizeof(mp));
memset(key,-1,sizeof(key));
scanf("%d%d%d%d",&n,&m,&p,&k);
for(int i=1;i<=k;i++){
int a,b,c,d,g;
scanf("%d%d%d%d%d",&a,&b,&c,&d,&g);
int x=gain(a,b),y=gain(c,d);
mp[x][y]=mp[y][x]=g;
}
scanf("%d",&k);
for(int i=1;i<=k;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
if(key[x][y]==-1) key[x][y]=0;
key[x][y]|=(1<<(z-1));
}
bfs();
printf("%d\n",ans);
return 0;
}