Note, that bfs can find right answer, but works in O(n·m·k). It’s too slow.
We’ll store all not visited cells in set. For each row and column we’ll make own set. Now it’s easy to find all not visited cell which is reachable from vertex in O(cnt·log(n)), where cnt is number of this cells. Then summary it works in O(n·m·log(n)).
注意,bfs可以找到正确答案,但适用于O(n·m·k)。太慢了。
我们将在set中存储所有未访问过的单元格。对于每一行和每一列,我们将创建自己的集合。现在很容易找到从O(cnt·log(n))的顶点可以到达的所有未访问的单元格,其中cnt是该单元格的数量。然后总结为O(n·m·log(n))
#include
using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
const int N = 1010;
char g[N][N];
int d[N][N];
int n,m,k;
int sx,sy,ex,ey;
int bfs()
{
if(sx==ex && sy==ey) return 0;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
memset(d,0x3f,sizeof d);
priority_queue<PIII,vector<PIII>,greater<PIII>> Q;
Q.push({0,{sx,sy}});
d[sx][sy]=0;
while(!Q.empty())
{
PIII t=Q.top();Q.pop();
for(int i=0;i<4;i++)
for(int j=1;j<=k;j++)
{
int x=t.second.first+dx[i]*j,y=t.second.second+dy[i]*j;
if(x<1 || x>n || y<1 || y>m || g[x][y]=='#') break;
if(d[x][y]>d[t.second.first][t.second.second]+1)
{
d[x][y]=d[t.second.first][t.second.second]+1;
if(x==ex && y==ey) return d[x][y];
Q.push({d[x][y],{x,y}});
}
}
}
return -1;
}
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++) cin>>(g[i]+1);
cin>>sx>>sy>>ex>>ey;
cout<<bfs();
return 0;
}
#include
using namespace std;
typedef pair<int,int> PII;
const int N = 1010;
char g[N][N];
int d[N][N];
int n,m,k;
int sx,sy,ex,ey;
int bfs()
{
if(sx==ex && sy==ey) return 0;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
memset(d,0x3f,sizeof d);
queue<PII> Q;
Q.push({sx,sy});
d[sx][sy]=0;
while(!Q.empty())
{
PII t=Q.front();Q.pop();
for(int i=0;i<4;i++)
for(int j=1;j<=k;j++)
{
int x=t.first+dx[i]*j,y=t.second+dy[i]*j;
if(x<1 || x>n || y<1 || y>m || g[x][y]=='#') break;
if(d[x][y]<d[t.first][t.second]+1) break;
if(d[x][y]>d[t.first][t.second]+1)
{
d[x][y]=d[t.first][t.second]+1;
if(x==ex && y==ey) return d[x][y];
Q.push({x,y});
}
}
}
return -1;
}
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++) cin>>(g[i]+1);
cin>>sx>>sy>>ex>>ey;
cout<<bfs();
return 0;
}