Submission #104939

#TimeUsernameProblemLanguageResultExecution timeMemory
104939Noam527Wall (CEOI14_wall)C++17
100 / 100
703 ms132400 KiB
#include <bits/stdc++.h>
#define CHECK cout << "ok" << endl
#define finish(x) return cout << x << endl, 0
typedef long long ll;
typedef long double ldb;
const int md = 1e9 + 7;
const ll inf = 1e18;
const int OO = 0;
const int OOO = 1;
using namespace std;

struct edge {
	int x, y, r;
	ll w;
	edge() {}
	edge(int xx, int yy, int rr, ll ww) : x(xx), y(yy), r(rr), w(ww) {}
	bool operator < (const edge &a) const {
		return w > a.w;
	}
};

int n, m;
vector<pair<int, int>> tar;
int V[404][404], H[404][404];
vector<edge> g[404][404];

ll dg[404][404];
bool found[404][404] = {};
pair<int, int> back[404][404];
bool block[404][404][4] = {};
bool blocked[404][404] = {};

vector<edge> t[404][404][4];
ll dt[404][404][4];


void dijk1() {
	for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) dg[i][j] = inf;
	priority_queue<edge> Q;
	Q.push(edge(0, 0, -1, 0));
	while (Q.size()) {
		edge x = Q.top();
		Q.pop();
		if (found[x.x][x.y]) continue;
		found[x.x][x.y] = 1;
		for (const auto &i : g[x.x][x.y]) {
			if (x.w + i.w < dg[i.x][i.y]) {
				dg[i.x][i.y] = x.w + i.w;
				back[i.x][i.y] = { x.x, x.y };
				Q.push(edge(i.x, i.y, -1, x.w + i.w));
			}
		}
	}
}

void applyblock(pair<int, int> x, pair<int, int> y) {
	if (x > y) swap(x, y);
	if (OO) {
		cout << "applying block on\n";
		cout << x.first << " " << x.second << '\n';
		cout << "to\n";
		cout << y.first << " " << y.second << '\n';
	}
	if (x.second == y.second) block[x.first][x.second][3] = block[y.first][y.second][1] = 1;
	else block[x.first][x.second][0] = block[y.first][y.second][2] = 1;
}

ll dijk2() {
	for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) for (int k = 0; k < 4; k++)
		dt[i][j][k] = inf;
	dt[0][0][1] = -1; // block cycle vertex
	priority_queue<edge> Q;
	Q.push(edge(0, 0, 0, 0));
	while (Q.size()) {
		edge x = Q.top();
		Q.pop();
		if (dt[x.x][x.y][x.r] != inf) continue;
		if (OO) {
			cout << "determined " << x.x << " " << x.y << " " << x.r << " = " << x.w << '\n';
		}
		dt[x.x][x.y][x.r] = x.w;
		for (const auto &i : t[x.x][x.y][x.r]) {
			if (dt[i.x][i.y][i.r] > x.w + i.w) {
				Q.push(edge(i.x, i.y, i.r, x.w + i.w));
			}
		}
	}
	return dt[0][0][2];
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	cin >> n >> m;
	for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) {
		int tmp;
		cin >> tmp;
		if (tmp) tar.emplace_back(i, j);
	}
	for (int i = 0; i < n; i++) for (int j = 0; j <= m; j++) cin >> V[i][j];
	for (int i = 0; i <= n; i++) for (int j = 0; j < m; j++) cin >> H[i][j];

	n++, m++;
	// make graph 1
	for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) {
		if (j + 1 < m) g[i][j].push_back(edge(i, j + 1, -1, H[i][j]));
		if (j - 1 >= 0) g[i][j].push_back(edge(i, j - 1, -1, H[i][j - 1]));
		if (i - 1 >= 0) g[i][j].push_back(edge(i - 1, j, -1, V[i - 1][j]));
		if (i + 1 < n) g[i][j].push_back(edge(i + 1, j, -1, V[i][j]));
	}
	dijk1();
	// now block....smh. track first
	if (OO) cout << "now tracking\n";
	for (const auto &i : tar) {
		pair<int, int> pos = i;
		while ((pos.first > 0 || pos.second > 0) && !blocked[pos.first][pos.second]) {
			blocked[pos.first][pos.second] = 1;
			applyblock(back[pos.first][pos.second], pos);
			pos = back[pos.first][pos.second];
		}
	}
	// block around targets
	if (OO) cout << "now around\n";
	for (const auto &i : tar) {
		pair<int, int> pos = i;
		applyblock(pos, { pos.first, pos.second + 1 });
		applyblock(pos, { pos.first + 1, pos.second });
		applyblock({ pos.first + 1, pos.second + 1 }, { pos.first, pos.second + 1 });
		applyblock({ pos.first + 1, pos.second + 1 }, { pos.first + 1, pos.second });
	}
	if (OO) {
		cout << "now some tests!!\n";
		cout << block[0][1][2] << '\n';
	}
	// make graph 2
	for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) {
		// 0
		if (i - 1 >= 0) t[i][j][0].push_back(edge(i - 1, j, 3, V[i - 1][j]));
		if (j + 1 < m) t[i][j][0].push_back(edge(i, j + 1, 1, H[i][j]));
		if (!block[i][j][0]) t[i][j][0].push_back(edge(i, j, 3, 0));
		if (!block[i][j][1]) t[i][j][0].push_back(edge(i, j, 1, 0));
		// 1
		if (i - 1 >= 0) t[i][j][1].push_back(edge(i - 1, j, 2, V[i - 1][j]));
		if (j - 1 >= 0) t[i][j][1].push_back(edge(i, j - 1, 0, H[i][j - 1]));
		if (!block[i][j][2]) t[i][j][1].push_back(edge(i, j, 2, 0));
		if (!block[i][j][1]) t[i][j][1].push_back(edge(i, j, 0, 0));
		// 2
		if (i + 1 < n) t[i][j][2].push_back(edge(i + 1, j, 1, V[i][j]));
		if (j - 1 >= 0) t[i][j][2].push_back(edge(i, j - 1, 3, H[i][j - 1]));
		if (!block[i][j][2]) t[i][j][2].push_back(edge(i, j, 1, 0));
		if (!block[i][j][3]) t[i][j][2].push_back(edge(i, j, 3, 0));
		// 3
		if (i + 1 < n) t[i][j][3].push_back(edge(i + 1, j, 0, V[i][j]));
		if (j + 1 < m) t[i][j][3].push_back(edge(i, j + 1, 2, H[i][j]));
		if (!block[i][j][0]) t[i][j][3].push_back(edge(i, j, 0, 0));
		if (!block[i][j][3]) t[i][j][3].push_back(edge(i, j, 2, 0));
	}
	cout << dijk2() << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...