Codeforces Round 442 (Div. 2) D. Olya and Energy Drinks
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))
优先队列的BFS
#include<bits/stdc++.h>
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;
}
普通的BFS (似乎比优先队列更快)
#include<bits/stdc++.h>
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;
}