题意:给你一个n*m的矩阵,每个格子可以移动到他上下左右四个格子.现在有些格子之间有门或墙.墙不能通过,每个门需要对应的钥匙打开.最多10种门,钥匙分布在某些格子上,走到这些格子上就能拿到钥匙.现在要从(1,1)走到(n,m)问最少要走多少步.如果不能到达输出-1.
样例解释:
4 49
9
1 2 1 3 2
1 2 2 2 0
2 1 2 2 0
2 1 3 1 0
2 3 3 3 0
2 4 3 4 1
3 2 3 3 0
3 3 4 3 0
4 3 4 4 0
2
2 1 2
4 2 1
有4*4的矩阵.其中有9个门或者墙:(1,2),(1,3)之间有门2.(1,2),(2,2)间是墙.....有两把钥匙:(2,1)上有钥匙2.(4,2)上有钥匙1.
解法:bfs基础上加 位运算.用一个数字记录当前拥有钥匙的情况.如:0000000011 (3)代表拥有钥匙1和2.然后判断点u到点v是否可以走.
代码:
#include <bits/stdc++.h> using namespace std; const int INF = 0x3f3f3f3f; int n,m,p; int g[3000][3000]; int ans=INF; int dis[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; int keylocal[800]; int vis[3000][1050]; struct node { int step,num; int keys; }; struct dian{ int x,y; }nod[3000]; bool haskey(int u,int v,node now) { if(g[u][v]==-1){ return true; } else{ int key=now.keys; int doors=g[u][v]; key>>=(doors-1); if(!(key & 1)){ return false; } return true; } } void bfs() { memset(vis,0,sizeof(vis)); queue<node> que; node now; now.keys=0; if(keylocal[1]){ int s=keylocal[1]; int count=1; while(s){ if(s&1){ int w=now.keys>>(count-1); if(!(w&1)){ now.keys=now.keys+(1<<(count-1)); } } s=s>>1; count++; } } now.num=1,now.step=0; que.push(now); while(!que.empty()){ node now=que.front(); que.pop(); int u=now.num; if(u==n*m){ ans=now.step; return ; } for(int i=0;i<4;i++){ int dx=nod[now.num].x+dis[i][0]; int dy=nod[now.num].y+dis[i][1]; int v=(dx-1)*m+dy; if(dx>=1 && dx<=n && dy>=1 && dy<=m && g[u][v]!=0 && haskey(u,v,now)&& !vis[v][now.keys]){ vis[v][now.keys]=1; node next; next.num=v; next.step=now.step+1; next.keys=now.keys; if(keylocal[v]){ int s=keylocal[v]; //cout<<"s "<<s<<endl; int count=1; while(s){ if((s & 1)){ int w=next.keys>>(count-1); if(!(w&1)){ next.keys=next.keys+(1<<(count-1)); } //cout<<"key "<<next.keys<<endl; //cout<<"keys "<<s<<endl; } s=s>>1; count++; } } que.push(next); } } } } void make() { int cnt=1; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ nod[cnt].x=i; nod[cnt++].y=j; } } for(int i=1;i<=n*m;i++){ for(int j=0;j<4;j++){ int dx=nod[i].x+dis[j][0]; int dy=nod[i].y+dis[j][1]; int v=(dx-1)*m+dy; if(dx>=1 && dx<=n && dy>=1 && dy<=m){ g[i][v]=-1; g[v][i]=-1; } } } } int main() { while(~scanf("%d%d%d",&n,&m,&p)){ ans=INF; int k; memset(g,0,sizeof(g)); memset(keylocal,0,sizeof(keylocal)); scanf("%d",&k); make(); for(int i=0;i<k;i++){ int x1,y1,x2,y2,w; scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&w); int u=(x1-1)*m+y1; int v=(x2-1)*m+y2; if(g[u][v]==-1){ g[u][v]=w; } else if(g[u][v]==0){ g[u][v]=0; } g[v][u]=g[u][v]; } int key; scanf("%d",&key); for(int i=0;i<key;i++){ int x,y,w; scanf("%d%d%d",&x,&y,&w); int s=keylocal[(x-1)*m+y]>>(w-1); if(!(s&1)){ keylocal[(x-1)*m+y]+=(1<<(w-1)); } } bfs(); if(ans>=INF){ printf("-1\n"); } else{ printf("%d\n",ans); } } return 0; }
时间: 2024-10-07 04:34:55