1 /**\
2 https://ac.nowcoder.com/acm/contest/26077/1005
3 从第i列第n行, 第1行m列添加起点, 然后bfs寻找能够分割两个点的墙
4
5 注意:
6 1、方向只能上下左右,因为对角线仍然可以穿过
7 2、处理图的数据的时候可以将-1的墙标记为成本为0,
8 为0的则不能变为墙,标记为1
9 3、使用优先队列优化搜索的时间
10 \**/
11 #include <bits/stdc++.h>
12 #define int long long
13 using namespace std;
14
15 const int N = 1e3 + 10;
16 const int d[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
17
18 int n, m, t;
19 int dis[N][N], g[N][N];
20
21 struct node {
22 int x, y, w;
23 bool operator < (const node& rhs) const {
24 return w > rhs.w;
25 }
26 };
27
28 void accept() {
29 for(int i = 1; i <= n; ++i) {
30 for(int j = 1; j <= m; ++j) {
31 dis[i][j] = 1e18;
32 cin >> g[i][j];
33 if(g[i][j] == -1) g[i][j] = 0;
34 else if(g[i][j] == 0) g[i][j] = -1;
35 }
36 }
37
38 priority_queue<node> q;
39
40 for(int i = 1; i <= n; ++i) {
41 if(g[i][1] != -1) {
42 dis[i][1] = g[i][1];
43 q.push({i, 1, g[i][1]});
44 }
45 }
46
47 for(int i = 1; i <= m; ++i) {
48 if(g[n][i] != -1) {
49 dis[n][i] = g[n][i];
50 q.push({n, i, g[n][i]});
51 }
52 }
53
54 int ok = -1;
55
56 while(!q.empty()) {
57 auto now = q.top();
58 q.pop();
59
60 if(now.x == 1 || now.y == m) {
61 ok = now.w;
62 break;
63 }
64
65 for(int i = 0; i < 4; ++i) {
66 int nx = now.x + d[i][0];
67 int ny = now.y + d[i][1];
68
69 if(nx < 1 || nx > n || ny < 1 || ny > m || g[nx][ny] == -1 || g[nx][ny] + now.w >= dis[nx][ny]) continue;
70
71 dis[nx][ny] = g[nx][ny] + now.w;
72 q.push({nx, ny, dis[nx][ny]});
73 }
74 }
75
76 cout << ok << "\n";
77 }
78
79 signed main()
80 {
81 ios::sync_with_stdio(false);
82 cin.tie(nullptr);
83
84 cin >> t >> n >> m;
85 for(int i = 0; i < t; ++i)
86 {
87 accept();
88 }
89 return 0;
90 }