#include <bits/stdc++.h>
#define int long long
#define endl '\n'
/*杭电春季赛1 1005 航线
小根堆优化dijkstra
*/
using namespace std;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vll = vector<long long>;
const int N = 1e5 + 10, inf = (1LL << 60) - 1, mod = 1e9 + 7;
const int dx[4] = {0, -1, 0, 1};
const int dy[4] = {1, 0, -1, 0};
int n, m, t[N], d[N];
int dis[N][4];//将一个点拆成4个方向的点
bool vis[N][4];//如上
//把x,y变成一维
int encode(int x, int y) {
return (x - 1) * m + y;
}
//再把一维变成二维
pii decode(int id) {
return make_pair((id - 1) / m + 1, (id - 1) % m + 1);
}
void wyx() {
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
cin >> t[encode(i, j)];
}
}
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
cin >> d[encode(i, j)];
}
}
int st = encode(1, 1);
int ed = encode(n, m);
for (int i = 1; i <= n * m; i ++ ) {
for (int j = 0; j < 4; j ++ ) {
dis[i][j] = inf;
vis[i][j] = 0;
}
}
priority_queue<
tuple<int, int, int>,
vector<tuple<int, int, int>>,
greater<tuple<int, int, int>>> pq;//用tuple来存储花销,位置,方向
//pq默认大根堆,模板第一个参数是存储的元素类型,第二个参数是底层容器类型,第三个参数是比较器类型
//若要改成小根堆就需要定义成priority_queue<xxx, vector<xxx>, greater<xxx>>
dis[st][0] = t[st];
pq.emplace(0, st, 0);//emplace对于插入复杂对象时可以直接构造对象,push适合已经构造好的对象
while (!pq.empty()) {
auto [val, p, u] = pq.top();
pq.pop();
if (vis[p][u]) continue;
vis[p][u] = 1;//已访问的位置不需要访问了
for (int v = 0; v < 4; v ++ ) {
if (dis[p][u] + d[p] >= dis[p][v]) continue;
dis[p][v] = dis[p][u] + d[p];
pq.emplace(dis[p][v], p, v);
}//更新一个点不同方向的最小花费
auto [x, y] = decode(p);
x += dx[u], y += dy[u];
int q = encode(x, y);
auto outmap = [&](int x, int y) {
return x < 1 || x > n || y < 1 || y > m;
};//判断越界
if (!outmap(x, y) && dis[p][u] + t[q] < dis[q][u]) {
dis[q][u] = dis[p][u] + t[q];
pq.emplace(dis[q][u], q, u);
}
}
cout << dis[ed][3] << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
wyx();
}
return 0;
}
春季算法练习1005
最新推荐文章于 2025-05-11 14:53:11 发布