Problem:
On or Off
Saving electricity is very important!
You are in the office represented as
R \times C
grid  that consists of walls and rooms.
It is guaranteed that, for any pair of rooms in the office, there exists exactly one route between the two rooms.
It takes 1 unit of time for you to move to the next room (that is, the grid adjacent to the current room).
Rooms are so dark that you need to switch on a light when you enter a room.
When you leave the room, you can either leave the light on, or
of course you can switch off the light. Each room keeps consuming electric power while the light is on.
Today you have a lot of tasks  across the office.
 Tasks are given as a list of coordinates, and they need to be done in the specified order.  
To save electricity, you want to finish all the tasks with the minimal amount of electric power.
The problem is not so easy though, because you  will consume electricity not only when light is on, but also when you switch on/off the light.

Luckily, you know the cost of power consumption per  unit time and also the cost to switch on/off the light for all the rooms in the office.
Besides, you are so smart that you don't need any  time to do the tasks themselves.
So please   figure out the optimal strategy  to minimize the amount of electric power consumed.
After you finished all the tasks, please DO NOT leave the light on at any room.
It's obviously wasting!
Input
The first line of the input contains three positive integers
R
(
0 \lt R \leq 50
),
C
(
0 \lt C \leq 50
) and
M
(
2 \leq M \leq 1000
).
The following
R
lines, which contain
C
characters each, describe the  layout of the office.
 '.' describes a room and  '#' describes a wall.
This is followed by three matrices with
R
rows,
C
columns each.
Every elements of the matrices are positive integers.
The
(r, c)
element in the first matrix describes the power consumption per unit of time for the room at the coordinate
(r, c)
.
The
(r, c)
element in the second matrix and the third matrix describe the cost to turn on the light and the cost to turn off the light, respectively, in the room at the coordinate
(r, c)
.
Each of the last
M
lines contains two positive integers, which describe the coodinates of the room for you to do the task.
Note that you cannot do  the
i
-th task if  any of the
j
-th task (
0 \leq j \leq i
) is left undone.
Output
Print one integer  that describes the minimal amount of electric power consumed when you finished all the tasks.
Sample Input 1
1 3 2
...
1 1 1
1 2 1
1 1 1
0 0
0 2
Output for the Sample Input 1
7
Sample Input 2
3 3 5
...
.##
..#
1 1 1
1 0 0
1 1 0
3 3 3
3 0 0
3 3 0
5 4 5
4 0 0
5 4 0
1 0
2 1
0 2
2 0
0 0
Output for the Sample Input 2
77
Sample Input 3
5 5 10
#.###
#....
###.#
..#.#
#....
0 12 0 0 0
0 4 3 2 10
0 0 0 99 0
11 13 0 2 0
0 1 1 2 1
0 4 0 0 0
0 13 8 2 4
0 0 0 16 0
1 1 0 2 0
0 2 3 1 99
0 2 0 0 0
0 12 2 12 2
0 0 0 3 0
4 14 0 16 0
0 2 14 2 90
0 1
3 0
4 4
1 4
1 1
4 4
1 1
4 3
3 0
1 4
Output for the Sample Input 3
777

Submitted solutions:

code_snippet: #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;

const int dx[]={1,0,0,-1};
const int dy[]={0,1,-1,0};

const int N = 55;
queue<int> q;
vector<int> path;
char mp[N][N];
int vis[N][N], pre[N][N], t[N*N];
int val[N][N], op[N][N], cl[N][N];
int n, m, K, X[N*N], Y[N*N];
void BFS(int sx, int sy, int ex, int ey) {
	while(!q.empty()) q.pop();
	memset(vis, -1, sizeof vis);
	memset(pre, -1, sizeof pre);

	vis[sx][sy] = 0;
	q.push(sx*N+sy);
	while(!q.empty()) {
		int tmp = q.front(); q.pop();
		int x = tmp / N, y = tmp % N;
		if(x == ex && y == ey) break;//continue;
		
		for(int di = 0; di < 4; di ++) {
			int nx = x + dx[di], ny = y + dy[di];
			if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
			if(vis[nx][ny] != -1 || mp[nx][ny] == '#') continue;
			
			vis[nx][ny] = vis[x][y] + 1;
			pre[nx][ny] = x*N+y;
			q.push(nx*N+ny);
		}
	}
	
	int size = 0, x = ex, y = ey;
	while(pre[x][y] != -1) {
		int tmp = pre[x][y];
		t[size++] = tmp;
		x = tmp / N;
		y = tmp % N;
	}
	for(int i = size-1; i >= 0; i --) path.push_back(t[i]);

}
void input() {
	for(int i = 0; i < n; i ++)
		scanf("%s", mp[i]);

	for(int i = 0; i < n; i ++) {
		for(int j = 0; j < m; j ++) {
			scanf("%d", &val[i][j]);
		}
	}
	for(int i = 0; i < n; i ++) {
		for(int j = 0; j < m; j ++) {
			scanf("%d", &op[i][j]);
		}
	}
	for(int i = 0; i < n; i ++) {
		for(int j = 0; j < m; j ++) {
			scanf("%d", &cl[i][j]);
		}
	}
	for(int i = 0; i < K; i ++) {
		scanf("%d%d", &X[i], &Y[i]);
	}
}
int main() {
	while(~scanf("%d%d%d", &n, &m, &K)) {
		input();
		//
		path.clear();
		for(int i = 1; i < K; i ++) {
			BFS(X[i-1], Y[i-1], X[i], Y[i]);
		}
		path.push_back(X[K-1]*N+Y[K-1]);
		
		memset(pre, -1, sizeof pre);
		int ans = 0;
		for(int i = 0; i < (int)path.size(); i ++) {
			int x = path[i]/N, y = path[i]%N;
			if(pre[x][y] == -1) {
				ans += op[x][y] + cl[x][y];
			} else {
				int tmp = (i - pre[x][y]) * val[x][y];
				tmp = min(tmp, op[x][y] + cl[x][y]);
				ans += tmp;
			}
			pre[x][y] = i;
		}
		
		printf("%d\n", ans);
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 13464
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
int Dist[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

void getPath(int startX, int startY, int finishX, int finishY, vector<pair<int, int>> &dest) {
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	Dist[startX][startY] = 0;
	bool found = 0;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			Dist[newX][newY] = Dist[currX][currY] + 1;
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY) {
				found = 1;
				break;
			}
		}
	}
	assert(found);
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	int newSize = dest.size() + Dist[currX][currY];
	assert(newSize < 2500000);
	dest.resize(newSize);
	--newSize;
	while (currX != startX || currY != startY) {
		dest[newSize--] = {currX, currY};
		tie(currX, currY) = from[currX][currY];
	}
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	scanf("%d %d %d", &N, &M, &Q);
	for (i = 0; i < N; ++i)
		scanf("%s", A[i]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &B[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &C[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &D[i][j]);

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	scanf("%d %d", &lastX, &lastY);
	while (Q-- > 1) {
		scanf("%d %d", &currX, &currY);
		assert(lastX != currX || lastY != currY);
		path.push_back({lastX, lastY});
		getPath(lastX, lastY, currX, currY, path);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	assert(path.size() < 2500000);

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	bool lightOn[NMAX][NMAX] = {};
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		answer += currAdd;
		if (!lightOn[path[i].first][path[i].second])
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			if (!lightOn[path[i].first][path[i].second])
				currAdd += B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 1;
		} else {
			if (lightOn[path[i].first][path[i].second])
				currAdd -= B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 0;
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 53052
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

vector<pair<int, int>> getPath(int startX, int startY, int finishX, int finishY) {
	vector<pair<int, int>> answer;
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	memset(from, 0, sizeof from);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY)
				break;
		}
	}
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	while (currX != startX || currY != startY) {
		answer.push_back({currX, currY});
		tie(currX, currY) = from[currX][currY];
	}
	reverse(answer.begin(), answer.end());
	return answer;
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	cin >> N >> M >> Q;
	for (i = 0; i < N; ++i)
		cin >> A[i];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> B[i][j];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> C[i][j];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> D[i][j];

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	cin >> lastX >> lastY;
	while (Q-- > 1) {
		cin >> currX >> currY;
		path.push_back({lastX, lastY});
		vector<pair<int, int>> currPath = getPath(lastX, lastY, currX, currY);
		for (auto it: currPath)
			path.push_back(it);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	bool lightOn[NMAX][NMAX] = {};
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		answer += currAdd;
		if (!lightOn[path[i].first][path[i].second])
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			if (!lightOn[path[i].first][path[i].second])
				currAdd += B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 1;
		} else {
			if (lightOn[path[i].first][path[i].second])
				currAdd -= B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 0;
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 54572
final_rank: 17

code_snippet: #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <queue>
using namespace std;
#define SZ(v) ((int)(v).size())
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define repf(i, a, b) for (int i = (a); i <= (b); ++i)
const int maxint = -1u>>1;
const int maxn = 50 + 2;
const int maxm = 1000 + 10;
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};

int r, c, m;
char s[maxn][maxn];
int open[maxn][maxn], inst[maxn][maxn], close[maxn][maxn];
pair<int, int> rec[maxm];
vector<pair<int, int> > p;
vector<int> tm[maxn][maxn];
bool used[maxn][maxn];

bool dfs(int x1, int y1, int x2, int y2) {
    if (x1 == x2 && y1 == y2) return true;
    if (used[x1][y1]) return false;
    used[x1][y1] = true;
    p.push_back(make_pair(x1, y1));
    for (int i = 0; i < 4; ++i) {
        int tx = x1 + dx[i], ty = y1 + dy[i];
        if (tx < 0 || ty < 0 || tx >= r || ty >= c || s[tx][ty] != '.') continue;
        if (dfs(tx, ty, x2, y2)) return true;
    }
    p.pop_back();
    return false;
}
int main() {
    while (scanf("%d%d%d", &r, &c, &m) == 3) {
        for (int i = 0; i < r; ++i) {
            scanf("%s", s[i]);
        }
        for (int i = 0; i < r; ++i) {
            for (int j = 0; j < c; ++j) {
                tm[i][j].clear();
                scanf("%d", &inst[i][j]);
            }
        }
        for (int i = 0; i < r; ++i) {
            for (int j = 0; j < c; ++j) {
                scanf("%d", &open[i][j]);
            }
        }
        for (int i = 0; i < r; ++i) {
            for (int j = 0; j < c; ++j) {
                scanf("%d", &close[i][j]);
            }
        }
        for (int i = 0; i < m; ++i) {
            scanf("%d%d", &rec[i].first, &rec[i].second);
        }
        int now = 0;
        for (int i = 1; i < m; ++i) {
            memset(used, 0, sizeof(used));
            p.clear();
            dfs(rec[i - 1].first, rec[i - 1].second, rec[i].first, rec[i].second);
            for (int j = 0; j < (int) p.size(); ++j) {
                tm[p[j].first][p[j].second].push_back(now);
                ++now;
            }
        }
        tm[rec[m - 1].first][rec[m - 1].second].push_back(now);
        int ans = 0;
        for (int i = 0; i < r; ++i) {
            for (int j = 0; j < c; ++j) {
                if (tm[i][j].size() == 0) continue;
                //printf("%d %d: ", i, j);for (int k = 0; k < (int)tm[i][j].size(); ++k) printf("%d ", tm[i][j][k]); printf("\n");
                ans += open[i][j] + close[i][j] + inst[i][j] * (tm[i][j].back() - tm[i][j].front());
                for (int k = 1; k < (int)tm[i][j].size(); ++k) {
                    if ((tm[i][j][k] - tm[i][j][k - 1]) * inst[i][j] > open[i][j] + close[i][j]) {
                        ans -= (tm[i][j][k] - tm[i][j][k - 1]) * inst[i][j] - open[i][j] - close[i][j];
                    }
                }
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 8628
final_rank: 1

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
int Dist[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

void getPath(int startX, int startY, int finishX, int finishY, vector<pair<int, int>> &dest) {
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	Dist[startX][startY] = 0;
	bool found = 0;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			Dist[newX][newY] = Dist[currX][currY] + 1;
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY) {
				found = 1;
				break;
			}
		}
	}
	assert(found);
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	int newSize = dest.size() + Dist[currX][currY];
	dest.resize(newSize);
	--newSize;
	while (currX != startX || currY != startY) {
		dest[newSize--] = {currX, currY};
		tie(currX, currY) = from[currX][currY];
	}
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	scanf("%d %d %d", &N, &M, &Q);
	for (i = 0; i < N; ++i)
		scanf("%s", A[i]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &B[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &C[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &D[i][j]);

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	scanf("%d %d", &lastX, &lastY);
	while (Q-- > 1) {
		scanf("%d %d", &currX, &currY);
		assert(lastX != currX || lastY != currY);
		path.push_back({lastX, lastY});
		getPath(lastX, lastY, currX, currY, path);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	assert(path.size() < 2500000);

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	bool lightOn[NMAX][NMAX] = {};
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		answer += currAdd;
		if (!lightOn[path[i].first][path[i].second])
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			if (!lightOn[path[i].first][path[i].second])
				currAdd += B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 1;
		} else {
			if (lightOn[path[i].first][path[i].second])
				currAdd -= B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 0;
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 53104
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
int Dist[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

void getPath(int startX, int startY, int finishX, int finishY, vector<pair<int, int>> &dest) {
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	Dist[startX][startY] = 0;
	bool found = 0;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			Dist[newX][newY] = Dist[currX][currY] + 1;
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY) {
				found = 1;
				break;
			}
		}
	}
	assert(found);
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	int newSize = dest.size() + Dist[currX][currY];
	dest.resize(newSize);
	--newSize;
	while (currX != startX || currY != startY) {
		dest[newSize--] = {currX, currY};
		tie(currX, currY) = from[currX][currY];
	}
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	scanf("%d %d %d", &N, &M, &Q);
	for (i = 0; i < N; ++i)
		scanf("%s", A[i]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &B[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &C[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &D[i][j]);

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	scanf("%d %d", &lastX, &lastY);
	while (Q-- > 1) {
		scanf("%d %d", &currX, &currY);
		assert(lastX != currX || lastY != currY);
		path.push_back({lastX, lastY});
		getPath(lastX, lastY, currX, currY, path);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	bool lightOn[NMAX][NMAX] = {};
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		answer += currAdd;
		if (!lightOn[path[i].first][path[i].second])
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			if (!lightOn[path[i].first][path[i].second])
				currAdd += B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 1;
		} else {
			if (lightOn[path[i].first][path[i].second])
				currAdd -= B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 0;
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 53172
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
int Dist[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

void getPath(int startX, int startY, int finishX, int finishY, vector<pair<int, int>> &dest) {
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	Dist[startX][startY] = 0;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			Dist[newX][newY] = Dist[currX][currY] + 1;
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY)
				break;
		}
	}
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	int newSize = dest.size() + Dist[currX][currY];
	dest.resize(newSize);
	--newSize;
	while (currX != startX || currY != startY) {
		dest[newSize--] = {currX, currY};
		tie(currX, currY) = from[currX][currY];
	}
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	scanf("%d %d %d", &N, &M, &Q);
	for (i = 0; i < N; ++i)
		scanf("%s", A[i]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &B[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &C[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &D[i][j]);

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	scanf("%d %d", &lastX, &lastY);
	while (Q-- > 1) {
		scanf("%d %d", &currX, &currY);
		assert(lastX != currX || lastY != currY);
		path.push_back({lastX, lastY});
		getPath(lastX, lastY, currX, currY, path);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	bool lightOn[NMAX][NMAX] = {};
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		answer += currAdd;
		if (!lightOn[path[i].first][path[i].second])
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			if (!lightOn[path[i].first][path[i].second])
				currAdd += B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 1;
		} else {
			if (lightOn[path[i].first][path[i].second])
				currAdd -= B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 0;
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 53132
final_rank: 13

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
int Dist[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

void getPath(int startX, int startY, int finishX, int finishY, vector<pair<int, int>> &dest) {
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	Dist[startX][startY] = 0;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			Dist[newX][newY] = Dist[currX][currY] + 1;
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY)
				break;
		}
	}
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	int newSize = dest.size() + Dist[currX][currY];
	dest.resize(newSize);
	--newSize;
	while (currX != startX || currY != startY) {
		dest[newSize--] = {currX, currY};
		tie(currX, currY) = from[currX][currY];
	}
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	scanf("%d %d %d", &N, &M, &Q);
	for (i = 0; i < N; ++i)
		scanf("%s", A[i]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &B[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &C[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &D[i][j]);

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	scanf("%d %d", &lastX, &lastY);
	while (Q-- > 1) {
		scanf("%d %d", &currX, &currY);
		path.push_back({lastX, lastY});
		getPath(lastX, lastY, currX, currY, path);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	bool lightOn[NMAX][NMAX] = {};
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		answer += currAdd;
		if (!lightOn[path[i].first][path[i].second])
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			if (!lightOn[path[i].first][path[i].second])
				currAdd += B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 1;
		} else {
			if (lightOn[path[i].first][path[i].second])
				currAdd -= B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 0;
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 53264
final_rank: 16

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

vector<pair<int, int>> getPath(int startX, int startY, int finishX, int finishY) {
	vector<pair<int, int>> answer;
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY)
				break;
		}
	}
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	while (currX != startX || currY != startY) {
		answer.push_back({currX, currY});
		tie(currX, currY) = from[currX][currY];
	}
	reverse(answer.begin(), answer.end());
	return answer;
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	scanf("%d %d %d", &N, &M, &Q);
	for (i = 0; i < N; ++i)
		scanf("%s", A[i]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &B[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &C[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &D[i][j]);

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	scanf("%d %d", &lastX, &lastY);
	while (Q-- > 1) {
		scanf("%d %d", &currX, &currY);
		path.push_back({lastX, lastY});
		vector<pair<int, int>> currPath = getPath(lastX, lastY, currX, currY);
		for (auto it: currPath)
			path.push_back(it);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	bool lightOn[NMAX][NMAX] = {};
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		answer += currAdd;
		if (!lightOn[path[i].first][path[i].second])
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			if (!lightOn[path[i].first][path[i].second])
				currAdd += B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 1;
		} else {
			if (lightOn[path[i].first][path[i].second])
				currAdd -= B[path[i].first][path[i].second];
			lightOn[path[i].first][path[i].second] = 0;
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 54868
final_rank: 18

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

vector<pair<int, int>> getPath(int startX, int startY, int finishX, int finishY) {
	vector<pair<int, int>> answer;
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	memset(from, 0, sizeof from);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY)
				break;
		}
	}
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	while (currX != startX || currY != startY) {
		answer.push_back({currX, currY});
		tie(currX, currY) = from[currX][currY];
	}
	reverse(answer.begin(), answer.end());
	return answer;
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	cin >> N >> M >> Q;
	for (i = 0; i < N; ++i)
		cin >> A[i];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> B[i][j];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> C[i][j];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> D[i][j];

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	cin >> lastX >> lastY;
	while (Q-- > 1) {
		cin >> currX >> currY;
		path.push_back({lastX, lastY});
		vector<pair<int, int>> currPath = getPath(lastX, lastY, currX, currY);
		for (auto it: currPath)
			path.push_back(it);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	set<pair<int, int>> lightOn;
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		answer += currAdd;
		if (!lightOn.count(path[i]))
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			if (!lightOn.count(path[i]))
				currAdd += B[path[i].first][path[i].second];
			lightOn.insert(path[i]);
		} else {
			if (lightOn.count(path[i]))
				currAdd -= B[path[i].first][path[i].second];
			lightOn.erase(path[i]);
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 55088
final_rank: 19

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];
bool witness[NMAX][NMAX];

vector<pair<int, int>> getPath(int startX, int startY, int finishX, int finishY) {
	vector<pair<int, int>> answer;
	queue<pair<int, int>> Q;

	memset(witness, 0, sizeof witness);
	memset(from, 0, sizeof from);
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY)
				break;
		}
	}
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	while (currX != startX || currY != startY) {
		answer.push_back({currX, currY});
		tie(currX, currY) = from[currX][currY];
	}
	reverse(answer.begin(), answer.end());
	return answer;
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	cin >> N >> M >> Q;
	for (i = 0; i < N; ++i)
		cin >> A[i];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> B[i][j];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> C[i][j];
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			cin >> D[i][j];

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	cin >> lastX >> lastY;
	while (Q-- > 1) {
		cin >> currX >> currY;
		path.push_back({lastX, lastY});
		vector<pair<int, int>> currPath = getPath(lastX, lastY, currX, currY);
		for (auto it: currPath)
			path.push_back(it);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	set<pair<int, int>> lightOn;
	int answer = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		for (auto it: lightOn)
			answer += B[it.first][it.second];
		if (!lightOn.count(path[i]))
			answer += C[path[i].first][path[i].second];
		E[path[i].first][path[i].second].pop_front();
		int front = E[path[i].first][path[i].second].front();
		if (E[path[i].first][path[i].second].size() && (front - i) * B[path[i].first][path[i].second] < C[path[i].first][path[i].second] + D[path[i].first][path[i].second]) {
			lightOn.insert(path[i]);
		} else {
			lightOn.erase(path[i]);
			answer += D[path[i].first][path[i].second];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 54896
final_rank: 20

code_snippet: #include<stdio.h>
#include<string.h>
int room[60][60]={0},step[60][60]={0},appear[60][60][1010]={0};
unsigned long long on[60][60],off[60][60],keep[60][60];
int tasks[1000][2]={0};
int n,m,ntask,total;
const int go[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

void indata()
{
  int i,j,k;
  scanf("%d %d %d\n",&n,&m,&ntask);
  for (i=1;i<=n;i++)
  {
    for (j=1;j<=m;j++)
    {
      if (getchar()=='.')
        room[i][j]=1;
    }
    getchar();
  }
  for (i=1;i<=n;i++)
    for (j=1;j<=m;j++)
      scanf("%d",&keep[i][j]);
  for (i=1;i<=n;i++)
    for (j=1;j<=m;j++)
      scanf("%d",&on[i][j]);
  for (i=1;i<=n;i++)
    for (j=1;j<=m;j++)
      scanf("%d",&off[i][j]);
  for (i=1;i<=ntask;i++)
  {
    scanf("%d%d",&tasks[i][0],&tasks[i][1]);
    tasks[i][0]++;
    tasks[i][1]++;
  }
}

int bfs(int aimx,int aimy,int nowx,int nowy,int time)
{
  int i,j,k;
  int x,y;
  for (i=0;i<4;i++)
  {
    x=nowx+go[i][0];
    y=nowy+go[i][1];
    if (room[x][y]&&(!step[x][y]))
    {
      step[x][y]=time;
      if ((aimx==x)&&(aimy==y))
      {
        appear[x][y][++appear[x][y][0]]=time;
        return time;
      }
      else
      {
        if (bfs(aimx,aimy,x,y,time+1))
        {
          appear[x][y][++appear[x][y][0]]=time;
          return time;
        }
      }
    }
  }
  return 0;
}

int main()
{
 /* freopen("input.txt","r",stdin);
  freopen("output.txt","w",stdout);*/
  int i,j,k,now;
  unsigned long long ans=0;
  indata();
  appear[tasks[1][0]][tasks[1][1]][0]=1;
  appear[tasks[1][0]][tasks[1][1]][1]=1;
  now=1;
  /*for (i=1;i<=ntask;i++)
    printf("%d %d\n",tasks[i][0],tasks[i][1]);*/
  for (i=2;i<=ntask;i++)
  {
    memset(step,0,sizeof(step));
    step[tasks[i-1][0]][tasks[i-1][1]]=now;
    bfs(tasks[i][0],tasks[i][1],tasks[i-1][0],tasks[i-1][1],now+1);
    now=step[tasks[i][0]][tasks[i][1]];
  }
 /* for (i=1;i<=n;i++)
    for (j=1;j<=m;j++)
    {
      printf("%d %d:",i,j);
      for (k=1;k<=appear[i][j][0];k++)
        printf(" %d",appear[i][j][k]);
      putchar('\n');
    }*/
  for (i=1;i<=n;i++)
    for (j=1;j<=m;j++)
    {
      if (appear[i][j][0])
        ans+=on[i][j]+off[i][j];
      for (k=1;k<appear[i][j][0];k++)
        if ((appear[i][j][k+1]-appear[i][j][k])*keep[i][j]>on[i][j]+off[i][j])
          ans+=on[i][j]+off[i][j];
        else
          ans+=(appear[i][j][k+1]-appear[i][j][k])*keep[i][j];
    }
  printf("%llu\n",ans);
 /* fclose(stdin);
  fclose(stdout);*/
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 14240
final_rank: 2

code_snippet: #include <bits/stdc++.h>

using namespace std;

const int NMAX = 60, PMAX = 1010;
const int dl[] = {1, 0, -1, 0};
const int dc[] = {0, 1, 0, -1};

int N, M, Q;
char A[NMAX][NMAX];
int B[NMAX][NMAX];
int C[NMAX][NMAX];
int D[NMAX][NMAX];
int Dist[NMAX][NMAX];
list<int> E[NMAX][NMAX];
pair<int, int> from[NMAX][NMAX];

void getPath(int startX, int startY, int finishX, int finishY, vector<pair<int, int>> &dest) {
	queue<pair<int, int>> Q;

	bool witness[NMAX][NMAX] = {};
	Q.push({startX, startY});
	witness[startX][startY] = 1;
	Dist[startX][startY] = 0;
	bool found = 0;
	while (!Q.empty()) {
		int currX, currY;
		tie(currX, currY) = Q.front();
		Q.pop();
		for (int i = 0; i < 4; ++i) {
			int newX = currX + dl[i];
			int newY = currY + dc[i];
			if (newX < 0 || newX >= N || newY < 0 || newY >= M)
				continue;
			if (A[newX][newY] != '.' || witness[newX][newY])
				continue;
			from[newX][newY] = {currX, currY};
			Dist[newX][newY] = Dist[currX][currY] + 1;
			witness[newX][newY] = 1;
			Q.push({newX, newY});
			if (newX == finishX && newY == finishY) {
				found = 1;
				break;
			}
		}
	}
	assert(found);
	int currX, currY;
	tie(currX, currY) = from[finishX][finishY];
	int newSize = dest.size() + Dist[currX][currY];
	assert(newSize < 2500000);
	dest.resize(newSize);
	--newSize;
	while (currX != startX || currY != startY) {
		dest[newSize--] = {currX, currY};
		tie(currX, currY) = from[currX][currY];
	}
}

int main() {
//	assert(freopen("debug.in", "r", stdin));
//	assert(freopen("debug.out", "w", stdout));

	int i, j;

	scanf("%d %d %d", &N, &M, &Q);
	for (i = 0; i < N; ++i)
		scanf("%s", A[i]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &B[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &C[i][j]);
	for (i = 0; i < N; ++i)
		for (j = 0; j < M; ++j)
			scanf("%d", &D[i][j]);

	vector<pair<int, int>> path;
	int lastX, lastY, currX, currY;
	scanf("%d %d", &lastX, &lastY);
	while (Q-- > 1) {
		scanf("%d %d", &currX, &currY);
		assert(lastX != currX || lastY != currY);
		path.push_back({lastX, lastY});
		getPath(lastX, lastY, currX, currY, path);
		lastX = currX, lastY = currY;
	}
	path.push_back({lastX, lastY});

	assert(path.size() < 2500000);

	for (size_t i = 0; i < path.size(); ++i)
		E[path[i].first][path[i].second].push_back(i);

	bool lightOn[NMAX][NMAX] = {};
	int answer = 0;
	int currAdd = 0;
	for (size_t i = 0; i < path.size(); ++i) {
		int x = path[i].first, y = path[i].second;
		answer += currAdd;
		if (!lightOn[x][y])
			answer += C[x][y];
		E[x][y].pop_front();
		int front = E[x][y].front();
		if (E[x][y].size() && (front - i) * B[x][y] < C[x][y] + D[x][y]) {
			if (!lightOn[x][y])
				currAdd += B[x][y];
			lightOn[x][y] = 1;
		} else {
			if (lightOn[x][y])
				currAdd -= B[x][y];
			lightOn[x][y] = 0;
			answer += D[x][y];
		}
	}

	cout << answer << '\n';
	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 53252
final_rank: 15

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
    int dx[4] = {1,0,-1,0}, dy[4] = {0,1,0,-1};
    int N, M, K;
    cin >> N >> M >> K;
    vector G(N,vector<bool>(M));
    rep(i,0,N) {
        string S;
        cin >> S;
        rep(j,0,M) G[i][j] = (S[j] == '.' ? true : false);
    }
    vector A(N,vector<int>(M)), B(N,vector<int>(M)), C(N,vector<int>(M));
    rep(i,0,N) rep(j,0,M) cin >> A[i][j];
    rep(i,0,N) rep(j,0,M) cin >> B[i][j];
    rep(i,0,N) rep(j,0,M) cin >> C[i][j];
    vector<int> X(K), Y(K);
    rep(i,0,K) cin >> X[i] >> Y[i];
    vector D(N, vector(M, vector<int>()));
    D[X[0]][Y[0]].push_back(0);
    rep(i,0,K-1) {
        vector Dist(N,vector<int>(M,inf));
        Dist[X[i+1]][Y[i+1]] = 0;
        queue<pair<int,int>> Q;
        Q.push({X[i+1],Y[i+1]});
        while(!Q.empty()) {
            auto [CurX, CurY] = Q.front();
            Q.pop();
            rep(j,0,4) {
                int NX = CurX + dx[j], NY = CurY + dy[j];
                if (0 <= NX && NX < N && 0 <= NY && NY < M && G[NX][NY]) {
                    if (chmin(Dist[NX][NY],Dist[CurX][CurY]+1)) Q.push({NX,NY});
                }
            }
        }
        int NowX = X[i], NowY = Y[i];
        while(1) {
            if (Dist[NowX][NowY] == 0) break;
            int NextX, NextY;
            rep(j,0,4) {
                int NX = NowX + dx[j], NY = NowY + dy[j];
                if (0 <= NX && NX < N && 0 <= NY && NY < M && G[NX][NY] && Dist[NX][NY] == Dist[NowX][NowY] - 1) {
                    NextX = NX, NextY = NY;
                    break;
                }
            }
            D[NextX][NextY].push_back(D[NowX][NowY].back()+1);
            NowX = NextX, NowY = NextY;
        }
    }
    int ANS = 0;
    rep(i,0,N) {
        rep(j,0,M) {
            if (D[i][j].empty()) continue;
            ANS += B[i][j] + C[i][j];
            rep(k,0,D[i][j].size()-1) {
                ANS += min(A[i][j]*(D[i][j][k+1]-D[i][j][k]),B[i][j]+C[i][j]);
            }
        }
    }
    cout << ANS << endl;
}
accuracy: 1
time_ms: 40
memory_kb: 8728
final_rank: 4

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

int main() {
    int H = in(), W = in(), M = in();
    vector<string> S = in(H);
    vector<vector<int>> c = in(H, W), on = in(H, W), off = in(H, W);
    vector<pair<int,int>> task = in(M);

    vector<pair<int,int>> pos;
    pos.push_back(task[0]);
    for(int k : rep(M - 1)) {
        vector dist(H, vector(W, -1));
        {
            auto [si, sj] = task[k + 1];
            dist[si][sj] = 0;
            queue<pair<int,int>> q;
            q.push({si, sj});
            while(not q.empty()) {
                auto [i, j] = q.front(); q.pop();
                for(auto [di, dj] : dir4) {
                    int ni = i + di, nj = j + dj;
                    if(0 <= ni and ni < H and 0 <= nj and nj < W and S[ni][nj] == '.' and dist[ni][nj] == -1) {
                        dist[ni][nj] = dist[i][j] + 1;
                        q.push({ni, nj});
                    }
                }
            }
        }

        auto [i, j] = task[k];
        do {
            for(auto [di, dj] : dir4) {
                int ni = i + di, nj = j + dj;
                if(0 <= ni and ni < H and 0 <= nj and nj < W and S[ni][nj] == '.' and dist[ni][nj] == dist[i][j] - 1) {
                    pos.push_back({ni, nj});
                    tie(i, j) = make_pair(ni, nj);
                    break;
                }
            }
        } while(dist[i][j] != 0);
    }

    vector T(H, vector(W, vector<int>()));
    for(int t : rep(int(pos.size()))) {
        auto [i, j] = pos[t];
        T[i][j].push_back(t);
    }

    int ans = 0;
    for(int i : rep(H)) for(int j : rep(W)) {
        vector<int> & ts = T[i][j];
        const int n = ts.size();
        bool is_on = false;
        int cost = 0;
        for(int k : rep(n)) {
            if(not is_on) {
                cost += on[i][j];
                is_on = true;
            }
            if(k + 1 < n and (ts[k + 1] - ts[k]) * c[i][j] <= off[i][j] + on[i][j]) {
                cost += (ts[k + 1] - ts[k]) * c[i][j];
            } else {
                cost += off[i][j];
                is_on = false;
            }
        }
        ans += cost;
    }
    print(ans);
}
accuracy: 1
time_ms: 40
memory_kb: 21460
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

#ifdef _RUTHEN
#include "debug.hpp"
#else
#define show(...) true
#endif

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
template <class T> using V = vector<T>;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int H, W, M;
    cin >> H >> W >> M;
    V<string> S(H);
    rep(i, H) cin >> S[i];
    V<V<int>> A(H, V<int>(W)), B(H, V<int>(W)), C(H, V<int>(W));
    rep(i, H) rep(j, W) cin >> A[i][j];
    rep(i, H) rep(j, W) cin >> B[i][j];
    rep(i, H) rep(j, W) cin >> C[i][j];
    V<int> X(M), Y(M);
    rep(i, M) cin >> X[i] >> Y[i];
    V<int> P;
    const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1}, INF = 1 << 30;
    rep(i, M - 1) {
        // calculate path
        V<V<int>> d(H, V<int>(W, INF)), pre(H, V<int>(W, -1));
        d[X[i]][Y[i]] = 0;
        queue<int> que;
        que.push(X[i] * W + Y[i]);
        while (!que.empty()) {
            int val = que.front();
            que.pop();
            int cx = val / W, cy = val % W;
            if (cx == X[i + 1] and cy == Y[i + 1]) break;
            rep(k, 4) {
                int nx = cx + dx[k], ny = cy + dy[k];
                if (!(0 <= nx and nx < H and 0 <= ny and ny < W)) continue;
                if (S[nx][ny] == '#') continue;
                if (d[nx][ny] != INF) continue;
                d[nx][ny] = d[cx][cy] + 1;
                pre[nx][ny] = cx * W + cy;
                que.push(nx * W + ny);
            }
        }
        V<int> PP;
        int cx = X[i + 1], cy = Y[i + 1];
        while (cx != X[i] or cy != Y[i]) {
            PP.push_back(pre[cx][cy]);
            int nx = pre[cx][cy] / W, ny = pre[cx][cy] % W;
            cx = nx, cy = ny;
        }
        reverse(PP.begin(), PP.end());
        for (auto p : PP) P.push_back(p);
    }
    P.push_back(X[M - 1] * W + Y[M - 1]);
    show(P);
    V<V<int>> lt(H, V<int>(W, -1));
    int N = P.size();
    ll ans = 0;
    for (int i = 0; i < N; i++) {
        int cx = P[i] / W, cy = P[i] % W;
        if (lt[cx][cy] != -1) {
            ans += min(A[cx][cy] * (i - lt[cx][cy]), B[cx][cy] + C[cx][cy]);
        } else {
            ans += B[cx][cy] + C[cx][cy];
        }
        lt[cx][cy] = i;
    }
    cout << ans << '\n';
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 13308
final_rank: 6

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi

namespace ebi {

void main_() {
    int r, c, m;
    std::cin >> r >> c >> m;
    std::vector<std::string> office(r);
    std::cin >> office;
    std::vector cost(r, std::vector<int>(c)), on(r, std::vector<int>(c)),
        off(r, std::vector<int>(c));
    std::cin >> cost >> on >> off;
    std::vector<std::pair<int, int>> tasks(m);
    std::cin >> tasks;
    auto calc_path = [&](int sy, int sx, int gy, int gx) -> std::vector<std::pair<int,int>> {
        std::queue<std::pair<int, int>> que;
        std::vector dist(r, std::vector<int>(c, INF));
        std::vector prev(r, std::vector<int>(c, -1));
        dist[sy][sx] = 0;
        que.push({sy, sx});
        while (!que.empty()) {
            auto [y, x] = que.front();
            que.pop();
            rep(i, 0, 4) {
                int ny = dy[i] + y;
                int nx = dx[i] + x;
                if (0 <= ny && ny < r && 0 <= nx && nx < c &&
                    office[ny][nx] == '.' && dist[ny][nx] == INF) {
                    dist[ny][nx] = dist[y][x] + 1;
                    prev[ny][nx] = i;
                    que.push({ny, nx});
                }
            }
        }
        std::vector<std::pair<int,int>> path;
        int y = gy, x = gx;
        while(prev[y][x] >= 0) {
            path.emplace_back(y, x);
            int idx = prev[y][x];
            int ny = y - dy[idx];
            int nx = x - dx[idx];
            assert(0 <= ny && ny < r && 0 <= nx && nx < c && office[ny][nx] == '.');
            y = ny;
            x = nx;
        }
        std::reverse(all(path));
        return path;
    };
    std::map<std::pair<int, int>, int> map;
    int ans = 0;
    std::vector<std::pair<int,int>> path;
    path.emplace_back(tasks[0]);
    rep(i,1,m) {
        auto [sy, sx] = tasks[i-1];
        auto [gy, gx] = tasks[i];
        auto p = calc_path(sy, sx, gy, gx);
        path.insert(path.end(), p.begin(), p.end());
    }
    int n = path.size();
    rep(i,0,n) {
        auto [y, x] = path[i];
        if(map.find({y, x}) == map.end()) {
            ans += on[y][x] + off[y][x];
        }
        else {
            int d = i - map[{y, x}];
            ans += std::min(d * cost[y][x], off[y][x] + on[y][x]);
        }
        map[{y, x}] = i;
    }
    std::cout << ans << '\n';
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 15244
final_rank: 10

code_snippet: /**
 *    author:  otera
**/
#include<bits/stdc++.h>
using namespace std;

#define int long long

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using int128_t = __int128_t;
#define repa(i, n) for(int i = 0; i < n; ++ i)
#define repb(i, a, b) for(int i = a; i < b; ++ i)
#define repc(i, a, b, c) for(int i = a; i < b; i += c)
#define overload4(a, b, c, d, e, ...) e
#define overload3(a, b, c, d, ...) d
#define rep(...) overload4(__VA_ARGS__, repc, repb, repa)(__VA_ARGS__)
#define rep1a(i, n) for(int i = 0; i <= n; ++ i)
#define rep1b(i, a, b) for(int i = a; i <= b; ++ i)
#define rep1c(i, a, b, c) for(int i = a; i <= b; i += c)
#define rep1(...) overload4(__VA_ARGS__, rep1c, rep1b, rep1a)(__VA_ARGS__)
#define rev_repa(i, n) for(int i=n-1;i>=0;i--)
#define rev_repb(i, a, b) assert(a > b);for(int i=a;i>b;i--)
#define rev_rep(...) overload3(__VA_ARGS__, rev_repb, rev_repa)(__VA_ARGS__)
#define rev_rep1a(i, n) for(int i=n;i>=1;i--)
#define rev_rep1b(i, a, b) assert(a >= b);for(int i=a;i>=b;i--)
#define rev_rep1(...) overload3(__VA_ARGS__, rev_rep1b, rev_rep1a)(__VA_ARGS__)
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
#define pb push_back
#define pf push_front
#define ppb pop_back
#define ppf pop_front
#define eb emplace_back
#define fr first
#define sc second
#define all(c) c.begin(),c.end()
#define rall(c) c.rbegin(), c.rend()
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
#define Sort(a) sort(all(a))
#define Rev(a) reverse(all(a))
#define Uniq(a) sort(all(a));a.erase(unique(all(a)),end(a))
#define si(c) (int)(c).size()
inline ll popcnt(ull a){ return __builtin_popcountll(a); }
#define kth_bit(x, k) ((x>>k)&1)
#define unless(A) if(!(A))
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll intpow(ll a, ll b, ll m) {ll ans = 1; while(b){ if(b & 1) (ans *= a) %= m; (a *= a) %= m; b /= 2; } return ans; }
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;in(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;in(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;in(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;in(__VA_ARGS__)
#define vec(type,name,...) vector<type>name(__VA_ARGS__)
#define VEC(type,name,size) vector<type>name(size);in(name)
#define vv(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));in(name)
#define vvv(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
template <class T, class U> using umap = unordered_map<T, U>;
template<class T> void scan(T& a){ cin >> a; }
template<class T> void scan(vector<T>& a){ for(auto&& i : a) scan(i); }
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){ scan(head); in(tail...); }
void print(){ cout << ' '; }
template<class T> void print(const T& a){ cout << a; }
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ cout << ' '; print(*i); } }
int out(){ cout << '\n'; return 0; }
template<class T> int out(const T& t){ print(t); cout << '\n'; return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); cout << ' '; out(tail...); return 0; }
#define CHOOSE(a) CHOOSE2 a
#define CHOOSE2(a0,a1,a2,a3,a4,x,...) x
#define debug_1(x1) cout<<#x1<<": "<<x1<<endl
#define debug_2(x1,x2) cout<<#x1<<": "<<x1<<", "#x2<<": "<<x2<<endl
#define debug_3(x1,x2,x3) cout<<#x1<<": "<<x1<<", "#x2<<": "<<x2<<", "#x3<<": "<<x3<<endl
#define debug_4(x1,x2,x3,x4) cout<<#x1<<": "<<x1<<", "#x2<<": "<<x2<<", "#x3<<": "<<x3<<", "#x4<<": "<<x4<<endl
#define debug_5(x1,x2,x3,x4,x5) cout<<#x1<<": "<<x1<<", "#x2<<": "<<x2<<", "#x3<<": "<<x3<<", "#x4<<": "<<x4<<", "#x5<<": "<<x5<<endl
#ifdef DEBUG
#define debug(...) CHOOSE((__VA_ARGS__,debug_5,debug_4,debug_3,debug_2,debug_1,~))(__VA_ARGS__)
#define dump(...) { print(#__VA_ARGS__); print(":"); out(__VA_ARGS__); }
#else
#define debug(...)
#define dump(...)
#endif

struct io_setup {
    io_setup(int precision = 20) {
        ios::sync_with_stdio(false);
        cin.tie(0);
        cout << fixed << setprecision(precision);
    }
} io_setup_ {};

const int inf = 1e9 + 7;

const int dx[4] = {0, 1, 0, -1};
const int dy[4] = {1, 0, -1, 0};

void solve() {
    INT(r, c, m);
    VEC(string, f, r);
    VV(int, c0, r, c);
    VV(int, c1, r, c);
    VV(int, c2, r, c);
    vc<int> x(m), y(m);
    rep(i, m) {
        in(x[i], y[i]);
    }
    int cur = 0;
    vvvc<int> g(r, vvc<int>(c, vc<int>()));
    auto mv = [&](int x1, int y1, int x2, int y2) -> void {
        debug(x1, y1, x2, y2);
        queue<P> que;
        vvc<int> di(r, vc<int>(c, inf));
        vvc<P> pre(r, vc<P>(c, P{-1, -1}));
        di[x1][y1] = cur;
        que.push(P{x1, y1});
        while(que.size()) {
            auto [x, y] = que.front(); que.pop();
            rep(_, 4) {
                int nx = x + dx[_], ny = y + dy[_];
                if(0 <= nx && nx < r && 0 <= ny && ny < c && f[nx][ny] == '.') {
                    if(chmin(di[nx][ny], di[x][y] + 1)) {
                        que.push(P{nx, ny});
                        pre[nx][ny] = P{x, y};
                    }
                }
            }
        }
        int x = x2, y = y2;
        while(true) {
            debug(x, y);
            g[x][y].eb(di[x][y]);
            auto [nx, ny] = pre[x][y];
            debug(nx, ny);
            if(nx == -1) break;
            x = nx; y = ny;
        }
        cur = di[x2][y2];
    };
    rep(i, m - 1) {
        mv(x[i], y[i], x[i + 1], y[i + 1]);
    }
    int ans = 0;
    rep(x, r) {
        rep(y, c) {
            auto v = g[x][y];
            int sz = si(v);
            if(sz == 0) continue;
            debug(x, y);
            dump(v);
            vvc<int> dp(sz, vc<int>(2, inf));
            dp[0][0] = c1[x][y] + c2[x][y];
            dp[0][1] = c1[x][y];
            for(int i = 1; i < sz; ++ i) {
                int ti = v[i] - v[i - 1];
                int val = min(dp[i - 1][0] + c1[x][y], dp[i - 1][1] + c0[x][y] * ti);
                chmin(dp[i][0], val + c2[x][y]);
                chmin(dp[i][1], val);
            }
            ans += dp[sz - 1][0];
        }
    }
    out(ans);
}

signed main() {
    int testcase = 1;
    // in(testcase);
    while(testcase--) solve();
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 13720
final_rank: 8

code_snippet: #line 1 "library/me/template.cpp"
// This is a dummy line
#ifndef ONLINE_JUDGE
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>
using namespace std;

#define REP(i, n) for(int i = 0; i < (int)(n); i++)
#define FOR(i, a, b) for(ll i = a; i < (ll)(b); i++)
#define ALL(a) (a).begin(),(a).end()
#define END(...) { print(__VA_ARGS__); return; }

#ifdef ONLINE_JUDGE
#define DBG(...) {}
#else
#define DBG(a) { cerr << #a << ": "; dbg(a); }
#endif

using VI = vector<int>;
using VVI = vector<VI>;
using VVVI = vector<VVI>;
using ll = long long;
using VL = vector<ll>;
using VVL = vector<VL>;
using VVVL = vector<VVL>;
using VD = vector<double>;
using VVD = vector<VD>;
using VVVD = vector<VVD>;
using VS = vector<string>;
using VVS = vector<VS>;
using VVVS = vector<VVS>;
using VC = vector<char>;
using VVC = vector<VC>;
using VVVC = vector<VVC>;
using P = pair<int, int>;
using VP = vector<P>;
using VVP = vector<VP>;
using VVVP = vector<VVP>;
using LP = pair<ll, ll>;
using VLP = vector<LP>;
using VVLP = vector<VLP>;
using VVVLP = vector<VVLP>;

template <typename T>
using PQ = priority_queue<T>;
template <typename T>
using GPQ = priority_queue<T, vector<T>, greater<T>>;

constexpr int INF = 1001001001;
constexpr ll LINF = 1001001001001001001ll;
constexpr int DX[] = {1, 0, -1, 0};
constexpr int DY[] = {0, 1, 0, -1};

#ifdef aclmodint

using MI7 = modint1000000007;
using V7 = vector<MI7>;
using VV7 = vector<V7>;
using VVV7 = vector<VV7>;
using MI3 = modint998244353;
using V3 = vector<MI3>;
using VV3 = vector<V3>;
using VVV3 = vector<VV3>;

ostream &operator<<(ostream &os, const modint &x) {
    os << x.val();
    return os;
}

ostream &operator<<(ostream &os, const MI3 &x) {
    os << x.val();
    return os;
}

ostream &operator<<(ostream &os, const MI7 &x) {
    os << x.val();
    return os;
}

istream &operator>>(istream &is, modint &x) {
    int y; is >> y;
    x = y;
    return is;
}

istream &operator>>(istream &is, MI3 &x) {
    int y; is >> y;
    x = y;
    return is;
}

istream &operator>>(istream &is, MI7 &x) {
    int y; is >> y;
    x = y;
    return is;
}

#endif

void print() { cout << '\n'; }
template<typename T>
void print(const T &t) { cout << t << '\n'; }
template<typename Head, typename... Tail>
void print(const Head &head, const Tail &... tail) {
    cout << head << ' ';
    print(tail...);
}

#ifdef ONLINE_JUDGE
template<typename... Args>
void dbg(const Args &... args) {}
#else
void dbg() { cerr << '\n'; }
template<typename T>
void dbg(const T &t) { cerr << t << '\n'; }
template<typename Head, typename... Tail>
void dbg(const Head &head, const Tail &... tail) {
    cerr << head << ' ';
    dbg(tail...);
}
#endif

template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
    os << p.first << " " << p.second;
    return os;
}

template< typename T1, typename T2 >
istream &operator>>(istream &is, pair< T1, T2 > &p) {
    is >> p.first >> p.second;
    return is;
}

template< typename T >
ostream &operator<<(ostream &os, const vector< T > &v) {
    for(int i = 0; i < (int) v.size(); i++) {
        os << v[i] << (i + 1 != (int) v.size() ? " " : "");
    }
    return os;
}

template< typename T >
istream &operator>>(istream &is, vector< T > &v) {
    for(T &in : v) is >> in;
    return is;
}

template< typename T1, typename T2 >
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template< typename T1, typename T2 >
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template <typename T>
pair<VI, vector<T>> compress(const vector<T> &a) {
    int n = a.size();
    vector<T> x;
    REP(i, n) x.push_back(a[i]);
    sort(ALL(x)); x.erase(unique(ALL(x)), x.end());
    VI res(n);
    REP(i, n) res[i] = lower_bound(ALL(x), a[i]) - x.begin();
    return make_pair(res, x);
}

template <typename T>
pair<vector<T>, vector<T>> factorial(int n) {
    vector<T> res(n+1), rev(n+1);
    res[0] = 1;
    REP(i, n) res[i+1] = res[i] * (i+1);
    rev[n] = 1 / res[n];
    for(int i = n; i > 0; i--) {
        rev[i-1] = rev[i] * i;
    }
    return make_pair(res, rev);
}

#ifdef aclsegtree

template<typename S>
struct value_size { S value; int size; };

template<typename S>
S min_op(S l, S r) { return min(l, r); };
template<typename S>
S max_op(S l, S r) { return max(l, r); };
template<typename S>
S sum_op(S l, S r) { return l + r; };
template<typename S>
value_size<S> sum_op_size(value_size<S> l, value_size<S> r) {
    return {l.value + r.value, l.size + r.size};
};

template<typename S>
S min_e() { return  numeric_limits<S>::max(); };
template<typename S>
S max_e() { return numeric_limits<S>::min(); };
template<typename S>
S sum_e() { return 0; }
template<typename S>
value_size<S> sum_e_size() { return {0, 0}; }
template<typename S>
value_size<S> min_e_size() { return {numeric_limits<S>::max(), 0}; }
template<typename S>
value_size<S> max_e_size() { return {numeric_limits<S>::min(), 0}; }

template<typename S, typename F>
S chmin_mapping(F f, S x) { return min(x, f); }
template<typename S, typename F>
S chmax_mapping(F f, S x) { return max(x, f); }
template<typename S, typename F>
S add_mapping(F f, S x) { return x + f; }
template<typename S, typename F>
value_size<S> add_mapping_size(F f, value_size<S> x) {
    return {x.value + x.size * f, x.size};
}
template <typename S,typename F, F ID>
S change_mapping(F f, S x) { return (f == ID? x : f); }
template <typename S,typename F, F ID>
value_size<S> change_mapping_size(F f, value_size<S> x) { 
    value_size<S> ret = {f * x.size, x.size};
    return (f == ID? x : ret); 
}
template <typename S, typename F1, typename F2>
S linear_mapping(pair<F1, F2> f, S x) { return x * f.first + f.second; }
template <typename S, typename F1, typename F2>
value_size<S> linear_mapping_size(pair<F1, F2> f, value_size<S> x) { return {x.value * f.first + x.size * f.second, x.size}; }

template<typename F>
F chmin_composition(F f, F g) { return min(f, g); }
template<typename F>
F chmax_composition(F f, F g) { return max(f, g); }
template<typename F>
F add_composition(F f, F g) { return f + g; }
template <typename F, F ID>
F change_composition(F f, F g) { return (f == ID? g : f); }
template<typename F1, typename F2>
pair<F1, F2> linear_composition(pair<F1, F2> f, pair<F1, F2> g) { return {f.first * g.first, f.first * g.second + f.second}; }

template<typename F>
F chmin_id() { return numeric_limits<F>::max(); }
template<typename F>
F chmax_id() { return numeric_limits<F>::min(); }
template<typename F>
F add_id() { return 0; }
template<typename F, F ID>
F change_id() { return ID; }
template<typename F1, typename F2>
pair<F1, F2> linear_id() { return {1, 0}; }

template<typename S>
using RSumQ = segtree<S, sum_op<S>, sum_e<S>>;
template<typename S>
using RMaxQ = segtree<S, max_op<S>, max_e<S>>;
template<typename S>
using RMinQ = segtree<S, min_op<S>, min_e<S>>;

template<typename S, typename F>
using RAddSumQ = lazy_segtree<value_size<S>, sum_op_size<S>, sum_e_size<S>,
    F, add_mapping_size<S, F>, add_composition<F>, add_id<F>>;
template<typename S, typename F>
using RAddMinQ = lazy_segtree<S, min_op<S>, min_e<S>,
    F, add_mapping<S, F>, add_composition<F>, add_id<F>>;
template<typename S, typename F>
using RAddMaxQ = lazy_segtree<S, max_op<S>, max_e<S>,
    F, add_mapping<S, F>, add_composition<F>, add_id<F>>;
template<typename S, typename F>
using RMinMinQ = lazy_segtree<S, min_op<S>, min_e<S>,
    F, chmin_mapping<S, F>, chmin_composition<F>, chmin_id<F>>;
template<typename S, typename F>
using RMaxMaxQ = lazy_segtree<S, max_op<S>, max_e<S>,
    F, chmax_mapping<S, F>, chmax_composition<F>, chmax_id<F>>;
template<typename S, typename F, F ID>
using RChangeMinQ = lazy_segtree<S, min_op<S>, min_e<S>,
    F, change_mapping<S, F, ID>,
    change_composition<F, ID>,
    change_id<F, ID>>;
template<typename S, typename F, F ID>
using RChangeMaxQ = lazy_segtree<S, max_op<S>, max_e<S>,
    F, change_mapping<S, F, ID>,
    change_composition<F, ID>,
    change_id<F, ID>>;
template<typename S, typename F, F ID>
using RChangeSumQ = lazy_segtree<value_size<S>, sum_op_size<S>, sum_e_size<S>,
    F, change_mapping_size<S, F, ID>,
    change_composition<F, ID>,
    change_id<F, ID>>;
template<typename S, typename F1, typename F2>
using RLinearMinQ = lazy_segtree<S, min_op<S>, min_e<S>,
    pair<F1, F2>, linear_mapping<S, F1, F2>,
    linear_composition<F1, F2>,
    linear_id<F1, F2>>;
template<typename S, typename F1, typename F2>
using RLinearMaxQ = lazy_segtree<S, max_op<S>, max_e<S>,
    pair<F1, F2>, linear_mapping<S, F1, F2>,
    linear_composition<F1, F2>,
    linear_id<F1, F2>>;
template<typename S, typename F1, typename F2>
using RLinearSumQ = lazy_segtree<value_size<S>, sum_op_size<S>, sum_e_size<S>,
    pair<F1, F2>, linear_mapping_size<S, F1, F2>,
    linear_composition<F1, F2>,
    linear_id<F1, F2>>;
#endif
#line 2 "Contests/Dummy/main.cpp"

bool run() {
    int m, n; cin >> m >> n;
    if(m == 0) return false;
    VS s(n); cin >> s;
    VI three_pow(m+1, 1);
    REP(i, m) three_pow[i+1] = three_pow[i] * 3;
    VI num(n, INF);
    REP(i, three_pow[m]) {
        VI v;
        int cnt;
        REP(j, n) {
            bool ok = true;
            cnt = 0;
            REP(k, m) {
                if(!(i / three_pow[k] % 3)) continue;
                cnt++;
                if(i / three_pow[k] % 3 - 1 != s[j][k] - '0') ok = false;
            }
            if(ok) v.push_back(j);
        }
        if(v.size() == 1) chmin(num[v[0]], cnt);
    }
    int ans = 0;
    REP(i, n) chmax(ans, num[i]);
    print(ans);
    return true;
}

void solve(){
    int r, c, m; cin >> r >> c >> m;
    VS maze(r); cin >> maze;
    VVL power(r, VL(c)), turnon(r, VL(c)), turnoff(r, VL(c)); cin >> power >> turnon >> turnoff;
    int prex, prey; cin >> prex >> prey;
    ll ans = turnon[prex][prey] + turnoff[prex][prey];
    VVL previsit(r, VL(c, -INF));
    previsit[prex][prey] = 0;
    ll t = 0;
    REP(i, m - 1) {
        int nxtx, nxty; cin >> nxtx >> nxty;
        VVL dist(r, VL(c, INF));
        dist[prex][prey] = 0;
        queue<P> que;
        que.emplace(prex, prey);
        while(!que.empty()) {
            auto [x, y] = que.front(); que.pop();
            REP(j, 4) {
                int nx = x + DX[j], ny = y + DY[j];
                if(nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
                if(maze[nx][ny] == '#') continue;
                if(dist[nx][ny] == INF) {
                    dist[nx][ny] = dist[x][y] + 1;
                    que.emplace(nx, ny);
                }
            }
        }
        int curx = nxtx, cury = nxty;
        while(curx != prex || cury != prey) {
            if(previsit[curx][cury] == -INF) ans += turnon[curx][cury]+turnoff[curx][cury];
            else ans += min(turnon[curx][cury]+turnoff[curx][cury], power[curx][cury]*(t+dist[curx][cury]-previsit[curx][cury]));
            previsit[curx][cury] = t + dist[curx][cury];
            REP(j, 4) {
                int nx = curx + DX[j], ny = cury + DY[j];
                if(nx < 0 || nx >= r || ny < 0 || ny >= c) continue;
                if(maze[nx][ny] == '#') continue;
                if(dist[nx][ny] + 1 == dist[curx][cury]) {
                    curx = nx, cury = ny;
                    break;
                }
            }
        }
        t += dist[nxtx][nxty];
        prex = nxtx, prey = nxty;
    }
    print(ans);
}

// generated by oj-template v4.7.2 (https://github.com/online-judge-tools/template-generator)
int main() {
    // Fasterize input/output script
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(100);
    // scanf/printf user should delete this fasterize input/output script

    int t = 1;
    //cin >> t; // comment out if solving multi testcase
    for(int testCase = 1;testCase <= t;++testCase){
        solve();
    }
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3612
final_rank: 5

code_snippet: #include "bits/stdc++.h"
using namespace std;

#define REP(a, b) for (long long a = 0; a < b; ++a)
#define ll long long
#define ld long double
#define ALL(x) begin(x), end(x)

#define int long long
int cost[3][100][100];
vector<int> cost_cutter[100][100];
void solve()
{
  int r, c, m;
  cin >> r >> c >> m;
  vector<string> inputs;
  REP(i, r)
  {
    string s;
    cin >> s;
    inputs.push_back(s);
  }
  REP(t, 3)
  {
    REP(i, r)
    {
      REP(q, c)
      {
        cin >> cost[t][i][q];
      }
    }
  }
  pair<int, int> cur;
  cin >> cur.first >> cur.second;
  cost_cutter[cur.first][cur.second].push_back(0);
  int cur_time = 0;
  REP(i, m - 1)
  {
    pair<int, int> target;
    cin >> target.first >> target.second;

    vector<vector<int>> dist(r, vector<int>(c, 1e18));
    vector<vector<pair<int, int>>> backs(r, vector<pair<int, int>>(c));

    dist[cur.first][cur.second] = 0;
    queue<pair<int, int>> nexts;
    nexts.push(cur);
    while (!nexts.empty())
    {
      pair<int, int> now = nexts.front();
      nexts.pop();
      int dx[4] = {-1, 1, 0, 0};
      REP(i, 4)
      {
        int x = dx[i] + now.first;
        int y = dx[3 - i] + now.second;
        if (x >= 0 and x < r and y >= 0 and y < c)
        {
          if (inputs[x][y] == '#')
            continue;
          if (dist[x][y] == 1e18)
          {
            dist[x][y] = dist[now.first][now.second] + 1;
            nexts.push({x, y});
            backs[x][y] = now;
          }
        }
      }
    }
    cur_time += dist[target.first][target.second];

    pair<int, int> now = target;
    while (now != cur)
    {
      cost_cutter[now.first][now.second].push_back(cur_time);
      cur_time--;
      now = backs[now.first][now.second];
    }
    cur_time += dist[target.first][target.second];

    cur = target;
  }

  int ans = 0;
  REP(i, r)
  {
    REP(q, c)
    {
      cost_cutter[i][q].push_back(1e12);
      REP(j, cost_cutter[i][q].size() - 1)
      {
        ans += cost[1][i][q];
        int next_come = cost_cutter[i][q][j + 1] - cost_cutter[i][q][j];
        next_come *= cost[0][i][q];
        if (j == cost_cutter[i][q].size() - 2 or next_come > cost[1][i][q] + cost[2][i][q])
        {
          ans += cost[2][i][q];
        }
        else
        {
          ans += next_come;
          ans -= cost[1][i][q];
        }
      }
    }
  }
  cout << ans << endl;
}

#undef int
int main()
{
  iostream::sync_with_stdio(false);
  cout << fixed << setprecision(100);
  solve();
}
accuracy: 1
time_ms: 50
memory_kb: 13904
final_rank: 7