常规思路分析:
使用BFS寻找最短路径,但是如果搜索到每个点的时候,对其上下左右分别进行k次新坐标的计算,再对每个计算出的新坐标进行判断有没有访问过的话,
时间复杂度可以达到:kmn,即1e9数量级,会超过时间
优化策略:
用集合(STL set)保存第i行还有哪些点没有被访问,用集合保存第j列还有哪些点没有被访问
在来到点(x,y)时,对于上下左右四个方向中的某一个,寻找,离这个点最近的点,然后将找到的点设置为新的基准点,再寻找在当前方向上,离这个基准点最近的新点,再将新点设置为基准点,如此反复,直到距离与(x,y)超过k或者是该点有垃圾
此时的复杂度为:mn*log(n)(每次找一个新点需要log(n)的复杂度,一共有mn个点)
#include<iostream>
#include<cstdio>
#include<queue>
#include<utility>
#include<set>
using namespace std;
const int maxn=1005;
int mp[maxn][maxn],vis[maxn][maxn],d[maxn][maxn];
int n,m,k,sx,sy,tx,ty,ans;
int dx[5]={-1,1,0,0},dy[5]={0,0,-1,1};
set<int> r[maxn],c[maxn];
void bfs(){
d[sx][sy]=0;
//vis[sx][sy]=1;
r[sx].erase(sy);
r[sy].erase(sx);
queue<pair<int,int>> q;
q.push({sx,sy});
while(q.size()){
pair<int,int> t=q.front();
q.pop();
int x=t.first,y=t.second;
if(x==tx && y==ty){
ans=d[x][y];
return;
}
//上
int cur=x;
while(1){
set<int>::iterator it=c[y].lower_bound(cur);
if(it==c[y].begin()){break;}
--it;
if(x-*it>k || mp[*it][y]==0) {break;}
cur=*it;
d[cur][y]=d[x][y]+1;
c[y].erase(cur);
r[cur].erase(y);
q.push({cur,y});
}
//下
cur=x;
while(1){
set<int>::iterator it=c[y].upper_bound(cur);
if(it==c[y].end()){break;}
if(*it-x>k || mp[*it][y]==0) {break;}
cur=*it;
d[cur][y]=d[x][y]+1;
c[y].erase(cur);
r[cur].erase(y);
q.push({cur,y});
}
//左
cur=y;
while(1){
set<int>::iterator it=r[x].lower_bound(cur);
if(it==r[x].begin()){break;}
--it;
if(y-*it>k || mp[x][*it]==0) {break;}
cur=*it;
d[x][cur]=d[x][y]+1;
c[cur].erase(x);
r[x].erase(cur);
q.push({x,cur});
}
//右
cur=y;
while(1){
set<int>::iterator it=r[x].upper_bound(cur);
if(it==r[x].end()){break;}
if(*it-y>k || mp[x][*it]==0) {break;}
cur=*it;
d[x][cur]=d[x][y]+1;
c[cur].erase(x);
r[x].erase(cur);
q.push({x,cur});
}
}
}
int main()
{
cin>>n>>m>>k;
//读入与初始化
for(int i=1;i<=n;i++){
string s;cin>>s;
for(int j=1;j<=m;j++){
if(s[j-1]=='.') mp[i][j]=1; //1是空位置 0是有垃圾
r[i].insert(j);
c[j].insert(i);
}
}
cin>>sx>>sy>>tx>>ty;
ans=-1;
bfs();
cout<<ans;
return 0;
}