思路比较简单:
01BFS跑最短路。
记录到达每个点的状态,dis[M][(1<<10 )+7]: 到达i点,状态为j的最小时间花费。
然后几个坑点:
1:钥匙无限使用
2:一个地方有多个钥匙,起点也会有钥匙
3:会有无解的情况 输出-1(bfs跑不出结果就是无解)
然后就是拼基本功了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define ls (o<<1)
#define rs (o<<1|1)
//#define m (l+r)/2
#define pb push_back
typedef pair<int,int> pii;
const double PI= acos(-1.0);
const int M = 15*15+7;
const int N = 15+7;
int mp[M][M];
vector<int>key[M];
int n,m;
int id(int x,int y){
return (x-1)*m+y;
}
struct node{
int x,y,d,sta;
};
int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
int dis[M][(1<<11)+7];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int p;
cin>>n>>m>>p;
int k;cin>>k;
for(int i=1;i<=k;i++){
int x1,y1,x2,y2,op;
cin>>x1>>y1>>x2>>y2>>op;
if(op==0)op=11;
int u=id(x1,y1),v=id(x2,y2);
mp[u][v]=mp[v][u]=op;
}
int nm;cin>>nm;
while(nm--){
int x,y,k;
cin>>x>>y>>k;
key[id(x,y)].push_back(k);
}
queue<node>q;
int st=0;
memset(dis,0x3f,sizeof(dis));
for(auto x:key[id(1,1)])st|=(1<<(x-1));
q.push(node{1,1,0,st});
dis[id(1,1)][st]=0;
while(q.size()){
node tp=q.front();q.pop();
int x=tp.x,y=tp.y,x2,y2,u=id(x,y),v,d=tp.d,sta=tp.sta;
if(x==n&&y==m){
cout<<d<<endl;
return 0;
}
for(int i=0;i<4;i++){
x2=x+dx[i];
y2=y+dy[i];
if(x2<1||x2>n||y2<1||y2>m)continue;
v=id(x2,y2);
if(mp[u][v]!=0 && !((sta>>(mp[u][v]-1))&1))continue;//u-v之间有墙或者有无法打开的门
int stb=sta;
for(auto z:key[v])stb|=(1<<(z-1));
if(dis[v][stb]>d+1){
dis[v][stb]=d+1;
q.push(node{x2,y2,d+1,stb});
}
}
}
cout<<-1<<endl;
return 0;
}