题目链接:http://codeforces.com/contest/877/problem/D
题意:求两点之间最短路啦,每次可以选择上下左右四种方向,可以走1~k步
思路:BFS+剪枝,如果某个方向上的点已经被同方向访问过了,那么以当前点为起点的这个方向的行动都可以用之前的代替,剪枝
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e3 + 5;
struct Node {
int x, y, time;
}now, nex;
int n, m, k, sx, sy, ex, ey;
int vis[MAXN][MAXN];
char mp[MAXN][MAXN];
int dx[4] = { 0,0,-1,1 };
int dy[4] = { -1,1,0,0 };
bool inBound(int x, int y) {
return x >= 1 && x <= n&&y >= 1 && y <= m;
}
bool bfs() {
now.x = sx; now.y = sy; now.time = 0;
vis[now.x][now.y] = (1 << 4) - 1;
queue<Node> q;
q.push(now);
while (!q.empty()) {
now = q.front(); q.pop();
if (now.x == ex && now.y == ey) {
return true;
}
for (int i = 0; i < 4; i++) {
for (int j = 1; j <= k; j++) {
nex.x = now.x + j*dx[i];
nex.y = now.y + j*dy[i];
if (!inBound(nex.x, nex.y) || (vis[nex.x][nex.y] & (1 << i)) || mp[nex.x][nex.y] == '#') break;
bool flag = false;
if (!vis[nex.x][nex.y]) {
flag = true;
}
vis[nex.x][nex.y] |= (1 << i);
if (flag) {
nex.time = now.time + 1;
q.push(nex);
}
}
}
}
return false;
}
int main() {
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= n; i++) {
scanf("%s", mp[i] + 1);
}
scanf("%d %d %d %d", &sx, &sy, &ex, &ey);
printf("%d\n", bfs() ? now.time : -1);
return 0;
}