传送门
【题目分析】
说是网络流24题但没看出哪里要用网络流。。。qwq也许我太菜了。
其实10*10的数据范围很容易想到暴力,但暴力可能会因为钥匙的存在而咕咕。
所以就考虑优化暴力。
发现钥匙种类不超过10种,所以考虑状压保存当前钥匙状态,0代表有,1代表没有。
然后就是一个坑点:一个地方可能有多把钥匙。。。
所以不能直接赋值而是同样用二进制表示当前位置的钥匙。
对于每一步,记录他的位置,用的步数和持有钥匙的情况,建一个优先队列,以步数为关键字。
然后就进行BFS,每走一步需要判断一下能不能走(两个点之间是否为墙,是否有当前门的钥匙)
因为用的是BFS,所以第一次走到终点即为最小步数,直接输出即可(结果我忘了还有-1这玩意儿qwq)
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=11;
const int MAXM=101;
const int INF=0x3f3f3f3f;
int n,m,p,k,s;
int flag=1;
int ma[MAXM][MAXM],key[MAXN][MAXN];
int dp[MAXN][MAXN][1<<MAXN];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
struct State{
int step;
int x,y;
int keys;
State(int a,int b,int c,int d){
step=a;
x=b,y=c;
keys=d;
}
friend inline bool operator<(const State &a,const State &b){
return a.step>b.step;
}
};
priority_queue<State> q;
int Read(){
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
int id(int x,int y){
return (x-1)*m+y;
}
int check(int state,int nx,int ny,int x,int y){
int a=id(nx,ny),b=id(x,y);
if(x<1||x>n||y<1||y>m)
return 0;
if(ma[a][b]==-1)
return 1;
else{
int c=ma[a][b];
if(state&(1<<(c-1)))
return 1;
return 0;
}
}
void bfs(){
State s(0,1,1,0);
q.push(s);
memset(dp,INF,sizeof(dp));
dp[1][1][0]=0;
while(!q.empty()){
State u=q.top();
q.pop();
if(u.x==n&&u.y==m){
cout<<u.step;
flag=0;
return ;
}
int x=u.x,y=u.y,sta=u.keys;
for(int i=0;i<4;++i){
int nx=x+dx[i],ny=y+dy[i];
if(check(u.keys,nx,ny,x,y)){
if(key[nx][ny]!=-1){
int c=key[nx][ny];
int nxt=sta|c;
if(dp[nx][ny][nxt]>dp[x][y][sta]+1){
dp[nx][ny][nxt]=dp[x][y][sta]+1;
State v(u.step+1,nx,ny,nxt);
q.push(v);
}
}
else{
if(dp[nx][ny][sta]>dp[x][y][sta]+1){
dp[nx][ny][sta]=dp[x][y][sta]+1;
State v(u.step+1,nx,ny,sta);
q.push(v);
}
}
}
}
}
}
int main(){
memset(ma,-1,sizeof(ma));
memset(key,-1,sizeof(key));
n=Read(),m=Read(),p=Read();
k=Read();
for(int i=1;i<=k;++i){
int x=Read(),y=Read(),a=Read(),b=Read(),g=Read();
int z=id(x,y),c=id(a,b);
ma[z][c]=g,ma[c][z]=g;
}
s=Read();
for(int i=1;i<=s;++i){
int x=Read(),y=Read(),q=Read();
if(key[x][y]==-1)
key[x][y]=0;
key[x][y]|=(1<<(q-1));
}
bfs();
if(flag)
puts("-1");
return 0;
}