This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/**
____ ____ ____ ____ ____
||a |||t |||o |||d |||o ||
||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int D_MAX = 400;
const int U = 0, R = 1, D = 2, L = 3;
const int UL = 0, UR = 1, DR = 2, DL = 3;
int N, M;
bool village[D_MAX][D_MAX];
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int cost[D_MAX + 1][D_MAX + 1][4];
bool isPoint (int x, int y) {
return (0 <= x && x <= N && 0 <= y && y <= M);
}
int backdir[D_MAX + 1][D_MAX + 1];
ll dist[D_MAX + 1][D_MAX + 1];
bool seen[D_MAX + 1][D_MAX + 1];
void minDistTree () {
for (int x = 0; x <= N; x++) {
for (int y = 0; y <= M; y++) {
dist[x][y] = LLONG_MAX;
seen[x][y] = false;
backdir[x][y] = -1;
}
}
priority_queue <tuple <ll, int, int>> q;
dist[0][0] = 0;
q.push(make_tuple(-dist[0][0], 0, 0));
while (q.empty() == false) {
ll d; int x, y; tie(d, x, y) = q.top();
q.pop();
if (seen[x][y] == true) {
continue;
}
seen[x][y] = true;
for (int dir = 0; dir < 4; dir++) {
int x1 = x + dx[dir], y1 = y + dy[dir];
if (isPoint(x1, y1) == true && dist[x][y] + cost[x][y][dir] < dist[x1][y1]) {
backdir[x1][y1] = (dir + 2) % 4;
dist[x1][y1] = dist[x][y] + cost[x][y][dir];
q.push(make_tuple(-dist[x1][y1], x1, y1));
}
}
}
}
bool edge[D_MAX + 1][D_MAX + 1][4];
void addEdge (int x, int y, int dir) {
edge[x][y][dir] = true;
edge[x + dx[dir]][y + dy[dir]][(dir + 2) % 4] = true;
}
ll cdist[D_MAX + 1][D_MAX + 1][4];
bool cseen[D_MAX + 1][D_MAX + 1][4];
ll solve () {
for (int x = 0; x <= N; x++) {
for (int y = 0; y <= M; y++) {
for (int c = 0; c < 4; c++) {
cdist[x][y][c] = LLONG_MAX;
cseen[x][y][c] = false;
}
}
}
priority_queue <tuple <ll, int, int, int>> q;
function <void (int, int, int, int, int, int, int)>
update = [&] (int x1, int y1, int c1, int x2, int y2, int c2, int cost) {
if (isPoint(x2, y2) == true && cdist[x1][y1][c1] + cost < cdist[x2][y2][c2]) {
cdist[x2][y2][c2] = cdist[x1][y1][c1] + cost;
q.push(make_tuple(-cdist[x2][y2][c2], x2, y2, c2));
}
};
cdist[0][0][UL] = LLONG_MIN;
cdist[0][0][UR] = 0;
q.push(make_tuple(-cdist[0][0][UR], 0, 0, UR));
while (q.empty() == false) {
ll d; int x, y, c; tie(d, x, y, c) = q.top();
q.pop();
if (cseen[x][y][c] == true) {
continue;
}
cseen[x][y][c] = true;
if (edge[x][y][c] == false) {
update(x, y, c, x, y, (c + 1) % 4, 0);
}
if (edge[x][y][(c + 3) % 4] == false) {
update(x, y, c, x, y, (c + 3) % 4, 0);
}
update(x, y, c, x + dx[c], y + dy[c], (c + 3) % 4, cost[x][y][c]);
update(x, y, c, x + dx[(c + 3) % 4], y + dy[(c + 3) % 4], (c + 1) % 4, cost[x][y][(c + 3) % 4]);
}
return cdist[0][0][DL];
}
int main () {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> N >> M;
for (int x = 0; x < N; x++) {
for (int y = 0; y < M; y++) {
cin >> village[x][y];
}
}
for (int x = 0; x < N; x++) {
for (int y = 0; y <= M; y++) {
cin >> cost[x][y][D];
cost[x + 1][y][U] = cost[x][y][D];
}
}
for (int x = 0; x <= N; x++) {
for (int y = 0; y < M; y++) {
cin >> cost[x][y][R];
cost[x][y + 1][L] = cost[x][y][R];
}
}
minDistTree();
for (int x = 0; x < N; x++) {
for (int y = 0; y < M; y++) {
if (village[x][y] == true) {
int x1 = x, y1 = y;
while (backdir[x1][y1] != -1) {
int dir = backdir[x1][y1];
int x2 = x1 + dx[dir], y2 = y1 + dy[dir];
addEdge(x1, y1, dir);
x1 = x2; y1 = y2;
}
addEdge(x, y, R);
addEdge(x, y, D);
addEdge(x + 1, y, R);
addEdge(x, y + 1, D);
}
}
}
cout << solve() << "\n";
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |