#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n;cin>>n;

    bool case2 = true, case3 = true;

    vector<vector<bool>> vec(n, vector<bool>(n));
    vector<vector<int>> tox(n, vector<int>(n));
    vector<vector<int>> temp(n, vector<int>(n, INT_MAX));

    priority_queue<pair<int, pair<int, int>>> sand;
    vector<int> t;

    for (int i = 0; i < n; ++i){
        for (int j = 0; j < n; ++j){
            char c; cin>>c;
            vec[i][j] = c == '1';

            if (vec[i][j]){
                case2 = false;
            }else{

                temp[i][j] = 0;

                if (i > 0){
                    sand.push({1, {i - 1, j}});
                    temp[i - 1][j] = 1;
                }

                if (j > 0){
                    sand.push({1, {i, j - 1}});
                    temp[i][j - 1] = 1;
                }

                if (i < n - 1){
                    sand.push({1, {i + 1, j}});
                    temp[i + 1][j] = 1;
                }

                if (j < n - 1){
                    sand.push({1, {i, j + 1}});
                    temp[i][j + 1] = 1;
                }
            }
        }
    }

    for (int i = 0; i < n; ++i){
        for (int j = 0; j < n; ++j){
            cin>>tox[i][j];

            if (tox[i][j] < 0)
                case3 = false;
        }
    }

    while (!sand.empty()){
        auto p = sand.top();
        int i = p.second.first, j = p.second.second;

        if (i > 0 && temp[i - 1][j] == INT_MAX){
           sand.push({p.first + 1, {i - 1, j}});
           temp[i - 1][j] = p.first + 1;
        }

        if (j > 0 && temp[i][j - 1] == INT_MAX){
           sand.push({p.first + 1, {i, j - 1}});
           temp[i][j - 1] = p.first + 1;
        }

        if (i < n - 1 && temp[i + 1][j] == INT_MAX){
           sand.push({p.first + 1, {i + 1, j}});
           temp[i + 1][j] = p.first + 1;
        }

        if (j < n - 1 && temp[i][j + 1] == INT_MAX){
           sand.push({p.first + 1, {i, j + 1}});
           temp[i][j + 1] = p.first + 1;
        }

        sand.pop();
    }

    if (case2){
        vector<vector<int>> dp(n, vector<int>(n, INT_MAX));
        dp[0][0] = tox[0][0];

        for (int i = 0; i < n; ++i){
            for (int j = 0; j < n; ++j){
                if (i == 0 && j == 0)
                    continue;

                dp[i][j] = min(i > 0 ? (dp[i - 1][j] + tox[i][j]) : INT_MAX, j > 0 ? (dp[i][j - 1] + tox[i][j]) : INT_MAX);
            }
        }

        cout<<dp[n - 1][n - 1];
        return 0;
    }

    if (case3){
        vector<vector<int>> dp(n, vector<int>(n, INT_MAX));
        dp[0][0] = temp[0][0] == 0 ? tox[0][0] : 0;

        for (int i = 0; i < n; ++i){
            for (int j = 0; j < n; ++j){
                if (i == 0 && j == 0)
                    continue;

                int moves = i + j;
                int add = 0;

                if (moves >= temp[i][j]){
                    add = tox[i][j];
                }

                //cout<<i<<' '<<j<<' '<<temp[i][j]<<endl;

                dp[i][j] = min(i > 0 ? (dp[i - 1][j] + add) : INT_MAX, j > 0 ? (dp[i][j - 1] + add) : INT_MAX);
            }
        }

        cout<<dp[n - 1][n - 1];
        return 0;
    }

    return 0;
}