|
|
#include <bits/stdc++.h>
|
|
|
using namespace std;
|
|
|
|
|
|
const int N = 110, INF = 0x3f3f3f3f;
|
|
|
int n, m;
|
|
|
int g[N][N]; // 原始地图
|
|
|
int d[N][N]; // 记录最短距离,这个东西的作用是用来进行最优化剪枝,这个非常妙
|
|
|
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
|
|
|
|
|
|
void dfs(int x, int y, int cost, int used) {
|
|
|
if (d[x][y] <= cost) return; // 最优化剪枝,排除非最优路线
|
|
|
d[x][y] = cost; // 记录最优路线花费
|
|
|
if (x == m && y == m) return; // 递归出口
|
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
int nx = x + dx[i], ny = dy[i] + y;
|
|
|
if (nx < 1 || nx > m || ny < 1 || ny > m) continue;
|
|
|
|
|
|
if (g[nx][ny] == -1) { // 下一个位置是无色
|
|
|
if (used) continue; // 当前位置已使过魔法,下一个就无法继续使用魔法,无色不能变有色,无效
|
|
|
// 如果当前位置没有使用过魔法的话,下一个位置是可以使用魔法的,那么变成什么颜色呢?
|
|
|
// 你可以花费 2 个金币施展魔法让下一个无色格子暂时变为 你当前所处格子的颜色
|
|
|
g[nx][ny] = g[x][y];
|
|
|
dfs(nx, ny, cost + 2, 1); // 走入这个(nx,ny),标识费用+2,同时标注(nx,ny)的魔法是已使用状态,继续传递
|
|
|
g[nx][ny] = -1; // 也可以不走这个(nx,ny),需要回溯
|
|
|
} else if (g[nx][ny] == g[x][y]) // 下一个位置颜色相同
|
|
|
dfs(nx, ny, cost, 0); // 直接走过去,费用不变,也没有使用魔法
|
|
|
else
|
|
|
dfs(nx, ny, cost + 1, 0); // 有色到有色,颜色不同,花费1个金币,没有使用魔法
|
|
|
}
|
|
|
}
|
|
|
|
|
|
int main() {
|
|
|
// 加快读入
|
|
|
ios::sync_with_stdio(false), cin.tie(0);
|
|
|
cin >> m >> n;
|
|
|
|
|
|
memset(g, -1, sizeof g); // 标识无色是-1
|
|
|
while (n--) {
|
|
|
int a, b, c;
|
|
|
cin >> a >> b >> c;
|
|
|
g[a][b] = c; // 有颜色你就说是啥颜色吧
|
|
|
}
|
|
|
memset(d, 0x3f, sizeof d);
|
|
|
|
|
|
dfs(1, 1, 0, 0);
|
|
|
|
|
|
if (d[m][m] == INF)
|
|
|
puts("-1");
|
|
|
else
|
|
|
cout << d[m][m] << endl;
|
|
|
|
|
|
return 0;
|
|
|
} |