题目大意:
有一个机器人走迷宫,每次可以走一格或者三格,然后中间有一些障碍不能走,这些障碍会挡住机器人。
题解:
无权图最短路径,优先考虑BFS,在这里我们知道,这个题目有一个关键的hints就是每个格子能走4个方向(分别对应机器人的四个朝向),为什么要区分能走4个方向,而不是平时的BFS只能走一次呢?因为这里的机器人不同朝向时,往下一步走的cost不一样!同一个方向走到某一格(r,c)的时候,假如从起点到(r,c)cost更低了,我们才接受这一步,否则放弃这一步。这有点DP的意思在里面。
废话:
因为,输入数据的变量(M,N)的命名搞反了,WA了5发,而且当形状是正方形或者路线刚好就在范围里面的话还真看不出来问题,真是深刻教训! 这告诉我们,调试的时候,有时候看不出来问题,真应该多打印一些简单的变量看看。同时,这题给我们的启发是,这种BFS similar的题,可以多考虑每一个节点的状态,是否允许重复走的问题!
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int N, M;
const int MAXR = 60;
const int MAXC = 60;
const int MAXD = 4;
int inrange(int r, int c) {
return r >= 0 && r<M&&c >= 0 && c < N;
}
int main() {
int n, m;
while (cin >> m >> n && n&&m) {
if (n<2 || m<2)while (1);
N = n; M = m;
int chess[MAXR][MAXC];
memset(chess, 0, sizeof(chess));
for (int i = 0; i<m; i++) {
for (int j = 0; j<n; j++) {
int t;
cin >> t;
int r = i - 1;
int nxr = r + 1;
int c = j - 1;
int nxc = c + 1;
if (t == 1) {
if (inrange(r, c)) {
chess[r][c] = 1;
}
if (inrange(r, nxc))chess[r][nxc] = 1;
if (inrange(nxr, c))chess[nxr][c] = 1;
if (inrange(nxr, nxc))chess[nxr][nxc] = 1;
}
}
}
int ur, uc, desr, desc; int udir;
cin >> ur >> uc >> desr >> desc;
ur -= 1;
uc -= 1;
desr -= 1;
desc -= 1;
string stmp;
cin >> stmp;
if (stmp[0] == 's') { udir = 2; }
else if (stmp[0] == 'w')udir = 3;
else if (stmp[0] == 'n')udir = 0;
else if (stmp[0] == 'e')udir = 1;
else assert(0);
int dist[MAXR][MAXC][MAXD];
if(chess[ur][uc]){
cout<<-1<<endl;
return 0;
}
memset(dist, INF, sizeof(dist));
queue<pair<pair<int, int>, int>> q;
q.push(make_pair(make_pair(ur, uc), udir));
dist[ur][uc][udir] = 0;
const int dr[] = { 0,0,0,-1,-2,-3,0,0,0,1,2,3 };
const int dc[] = { -1,-2,-3,0,0,0,1,2,3,0,0,0 };
const int ddir[] = { 3,3,3,0,0,0,1,1,1,2,2,2 };
int par[MAXR*MAXC * 5];
memset(par, 0, sizeof(par));
while (!q.empty()) {
int ur = q.front().first.first;
int uc = q.front().first.second;
int udir = q.front().second;
q.pop();
for (int i = 0; i<12; i++) {
int nxr = ur + dr[i]; int nxc = uc + dc[i]; int nxdir = ddir[i];
if (nxr<0 || nxr >= m - 1 || nxc<0 || nxc >= n - 1)continue;
if (chess[nxr][nxc])continue;
if (nxr - ur == 3 && chess[ur + 1][nxc])continue;
if (nxr - ur == -3 && chess[ur - 1][nxc])continue;
if (nxc - uc == 3 && chess[ur][uc + 1])continue;
if (nxc - uc == -3 && chess[ur][uc - 1])continue;
int turnCost = 0;
if (udir == 1 || udir == 2)turnCost = abs(nxdir - udir);
else if (udir == 3) {
if (nxdir == 0 || nxdir == 2)turnCost = 1;
else if (nxdir == udir)turnCost = 0;
else turnCost = 2;
}
else {
if (nxdir == 1 || nxdir == 3)turnCost = 1;
else if (nxdir == udir) turnCost = 0;
else turnCost = 2;
}
if (dist[ur][uc][udir] + turnCost + 1 <dist[nxr][nxc][nxdir]) {
dist[nxr][nxc][nxdir] = dist[ur][uc][udir] + turnCost + 1;
int no=encode(nxr, nxc, nxdir);
par[no] = encode(ur, uc, udir);
q.push(make_pair(make_pair(nxr, nxc), nxdir));
}
}
}
if (dist[desr][desc][0] == INF && dist[desr][desc][1] == INF&&dist[desr][desc][2] == INF&& dist[desr][desc][3] == INF) {
cout << -1 << endl;
}
else {
priority_queue<int, vector<int>, greater<int>> pq;
for (int i = 0; i<4; i++)
{
pq.push(dist[desr][desc][i]);
}
cout << pq.top() << endl;
}
}
return 0;
}