题意:给你个n*m的方阵,放了空瓶子的不能走,每次可以从一个地方向上下左右走不超过k步,问从起点到终点的最小步数
思考:每一个格点都可以向4个方向走1~k步,普通的bfs中从一个方向来了走到nx,ny之后,nx和ny就不能再被经过了。但是在本题中,可能我从上方走到nx,ny是到nx,ny最短的,但是我还能从左方走经过nx,ny到别的地方使别的地方花费时间最短。因此将一个点只能经过一次,改成一个点从每个方向只能经过一次,不过第一次访问到nx,ny时还是到这个点的最短花费。
#include<bits/stdc++.h>
using namespace std;
const int M=1010;
string s[M];
int d[M][M];
int vis[M][M];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int n,m,k;
int x1,x2,t1,t2;
struct node
{
int x,y;
node(){};
node(int x,int y):x(x),y(y){}
};
int solve()
{
queue<node> q;
memset(d,-1,sizeof(d));
d[x1][t1]=0;
q.push(node(x1,t1));
vis[x1][t1]=(1<<4)-1; //四个方向都不可以再过来了
while(!q.empty())
{
node tmp=q.front();
q.pop();
int x=tmp.x,y=tmp.y;
if(x==x2&&y==t2) return d[x2][t2];
for(int i=0;i<4;++i)
{
for(int j=1;j<=k;++j)
{
int nx=x+j*dx[i],ny=y+j*dy[i];
if(nx>0&&nx<n&&ny>0&&ny<m&&s[nx][ny]!='#'&&!(vis[nx][ny]&(1<<i))) //没有从i方向来过
{
if(d[nx][ny]==-1)
{
d[nx][ny]=d[x][y]+1;
q.push(node(nx,ny));
}
}
vis[nx][ny]|=1<<i; //这个方向来过
}
}
}
}
int main()
{
for(int i=0;i<n;++i)
cin>>s[i];
cin>>x1>>t1>>x2>>t2;
int ans=solve();
cout<<ans<<endl;
}