1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| #include <bits/stdc++.h> using namespace std; typedef pair<int, int> pii; typedef long long ll; const ll INF = 0x3f3f3f3f3f3f3f3f; const int N = 505; const int K = 55;
struct Node{ int x, y; ll dis; bool operator < (const Node& other) const { return dis > other.dis; } };
int v[N][N], h[N][N]; pii entry[N << 2], point[K]; vector<pii> start[K]; ll G[K][K], dis[N][N], f[N][N];
int n, m;
void dijkstra(int s) { priority_queue<Node> pq; for (int i = 0; i <= n; i++) for (int j = 0; j <= m; j++) dis[i][j] = INF; for (auto& p : start[s]) { dis[p.first][p.second] = 0; pq.push({p.first, p.second, 0}); } while (!pq.empty()) { Node cur = pq.top(); pq.pop(); if (cur.dis > dis[cur.x][cur.y]) continue; if (cur.x > 0) { Node nxt = Node({cur.x - 1, cur.y, cur.dis + h[cur.x][cur.y]}); if (nxt.dis < dis[nxt.x][nxt.y]) { dis[nxt.x][nxt.y] = nxt.dis; pq.push(nxt); } } if (cur.x < n) { Node nxt = Node({cur.x + 1, cur.y, cur.dis + h[cur.x + 1][cur.y]}); if (nxt.dis < dis[nxt.x][nxt.y]) { dis[nxt.x][nxt.y] = nxt.dis; pq.push(nxt); } } if (cur.y > 0) { Node nxt = Node({cur.x, cur.y - 1, cur.dis + v[cur.x][cur.y]}); if (nxt.dis < dis[nxt.x][nxt.y]) { dis[nxt.x][nxt.y] = nxt.dis; pq.push(nxt); } } if (cur.y < m) { Node nxt = Node({cur.x, cur.y + 1, cur.dis + v[cur.x][cur.y + 1]}); if (nxt.dis < dis[nxt.x][nxt.y]) { dis[nxt.x][nxt.y] = nxt.dis; pq.push(nxt); } } } }
ll dp(int l, int r) { if (l > r) return 0; if (f[l][r] != -1) return f[l][r]; if (l + 1 == r) return f[l][r] = G[l][r]; f[l][r] = INF; for (int k = l + 1; k <= r; k += 2) f[l][r] = min(f[l][r], G[l][k] + dp(l + 1, k - 1) + dp(k + 1, r)); return f[l][r]; }
int main() { int T; scanf("%d%d%d", &n, &m, &T); for (int i = 1; i < n; i++) for (int j = 1; j <= m; j++) scanf("%d", &v[i][j]); for (int i = 1; i <= n; i++) for (int j = 1; j < m; j++) scanf("%d", &h[i][j]); for (int i = 0; i < m; i++) entry[i] = {0, i}; for (int i = m; i < m + n; i++) entry[i] = {i - m, m}; for (int i = m + n; i < 2 * m + n; i++) entry[i] = {n, 2 * m + n - i}; for (int i = 2 * m + n; i < 2 * (m + n); i++) entry[i] = {2 * m + 2 * n - i, 0}; while (T--) { int k; scanf("%d", &k); for (int i = 0, x; i < k; i++) { scanf("%d%d%d", &x, &point[i].first, &point[i].second); if (point[i].first <= m) v[0][point[i].first] = x; else if (point[i].first <= m + n) h[point[i].first - m][m] = x; else if (point[i].first <= 2 * m + n) v[n][2 * m + n - point[i].first + 1] = x; else h[2 * (m + n) - point[i].first + 1][0] = x; } sort(point, point + k); int source = 0; for (int i = 1; i < k; i++) if (point[i].second != point[i - 1].second) { start[source].clear(); for (int j = point[i - 1].first; j < point[i].first; j++) start[source].push_back(entry[j]); source++; } if (point[0].second != point[k - 1].second) { start[source].clear(); for (int j = point[k - 1].first; j < 2 * (n + m); j++) start[source].push_back(entry[j]); for (int j = 0; j < point[0].first; j++) start[source].push_back(entry[j]); source++; } for (int i = 0; i < source - 1; i++) { dijkstra(i); for (int j = i + 1; j < source; j++) { ll d = INF; for (auto& p : start[j]) d = min(d, dis[p.first][p.second]); G[i][j] = G[j][i] = d; } } memset(f, -1, sizeof(f)); printf("%lld\n", dp(0, source - 1)); for (int i = 0; i <= m; i++) v[0][i] = v[n][i] = 0; for (int i = 0; i <= n; i++) h[i][0] = h[i][m] = 0; } return 0; }
|