#include <vector>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using vi = vector<int>;
using vll = vector<ll>;
using vvi = vector<vi>;
using vvll = vector<vll>;
using pii = vector<pair<int, int>>;
using pll = vector<pair<ll, ll>>;
using vvpii = vector<vector<pii>>;
template <typename T>
using max_pq = priority_queue<T>;
template <typename T>
using min_pq = priority_queue<T, vector<T>, greater<T>>;
constexpr int MOD = 1000000007;
constexpr int IINF = 1000000000;
constexpr ll LLINF = 1000000000000000000;
constexpr double EPS = 1e-9;
void set_io(string name = "") {
if (!name.empty()) {
freopen((name + ".INP").c_str(), "r", stdin);
freopen((name + ".OUT").c_str(), "w", stdout);
}
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
}
template <typename T>
void read_vector(vector<T>& vec, const size_t n) {
vec.resize(n);
for (size_t i = 0; i < n; ++i) {
cin >> vec[i];
}
}
template <typename T>
void print_vector(const vector<T>& vec) {
cout << "[";
for (size_t i = 0; i < vec.size(); ++i) {
cout << vec[i];
if (i < vec.size() - 1) {
cout << ", ";
}
}
cout << "]" << endl;
}
template <typename T>
void print_2d_vector(const vector<vector<T>>& vec) {
cout << "[";
for (size_t i = 0; i < vec.size(); ++i) {
if (i > 0) cout << " ";
cout << "[";
for (size_t j = 0; j < vec[i].size(); ++j) {
cout << vec[i][j];
if (j < vec[i].size() - 1) {
cout << ", ";
}
}
cout << "]";
if (i < vec.size() - 1) {
cout << "," << endl;
}
}
cout << "]" << endl;
}
void log() {cerr << endl;}
template <typename T, typename... Args>
void log(T first, Args... args) {
cerr << first << ' ';
log(args...);
}
template <bool IsDirected, bool IsWeighted>
auto read_graph(int n, int m) {
if constexpr (IsWeighted) {
vvpii adj(n);
for (int i = 0; i < m; ++i) {
int u, v, w;
cin >> u >> v >> w;
--u; --v;
adj[u].emplace_back(v, w);
if constexpr (!IsDirected) adj[v].emplace_back(u, w);
}
return adj;
} else {
vvi adj(n);
for (int i = 0; i < m; ++i) {
int u, v;
cin >> u >> v;
--u; --v;
adj[u].push_back(v);
if constexpr (!IsDirected) adj[v].push_back(u);
}
return adj;
}
}
template<typename T>
bool chmin(T& a, const T& b) {
if (b < a) { a = b; return true; }
return false;
}
template<typename T>
bool chmax(T& a, const T& b) {
if (a < b) { a = b; return true; }
return false;
}
template <typename T>
vector<long long> make_prefix_sum(const vector<T>& arr) {
int n = arr.size();
vector<ll> pref(n + 1, 0);
for (int i = 0; i < n; ++i) {
pref[i + 1] = pref[i] + arr[i];
}
return pref;
}
template <typename T>
bool is_valid(int r, int c, int R, int C) {
return r >= 0 && r < R && c >= 0 && c < C;
}
void sub1(vvi& grid) {
int n = (grid.size() + 1) / 2;
vector<int> max_row;
for (auto& row : grid) {
max_row.push_back(*max_element(row.begin(), row.end()));
}
vector<vvll> dp(2, vvll(2 * n));
for (int i = 0; i <= n; ++i) {
dp[0][i].resize(n + i - 1, 0);
dp[1][i].resize(n + i - 1, 0);
}
for (int i = n + 1; i < 2 * n; ++i) {
dp[0][i].resize(2 * n - 1 - (i - n), 0);
dp[1][i].resize(2 * n - 1 - (i - n), 0);
}
for (int t = 0; t < 2; ++t) {
for (int i = 1; i < 2 * n; ++i) {
int curr_sz = dp[0][i].size();
int prev_sz = dp[0][i - 1].size();
for (int j = 0; j < curr_sz; ++j) {
int a, b;
ll s = 0;
if (i <= n) {a = j - 1; b = j;}
else {a = j; b = j + 1;}
if (a >= 0) {
s = dp[t][i - 1][a];
}
if (b < prev_sz) {
s = max(s, dp[t][i - 1][b]);
}
dp[t][i][j] = max(dp[t][i][j], s + grid[i - 1][j]);
if (t == 0) {
dp[1][i][j] = max(dp[1][i][j], s + max_row[i - 1]);
}
}
}
}
cout << max(*max_element(dp[0][2 * n - 1].begin(), dp[0][2 * n - 1].end()),
*max_element(dp[1][2 * n - 1].begin(), dp[1][2 * n - 1].end())) << '\n';
}
void sub2(vvi& grid) {
int n = (grid.size() + 1) / 2;
vector<pair<int, int>> stats(2 * n - 1);
for (int i = 0; i < 2 * n - 1; ++i) {
int m1 = -1, m2 = -1;
for (int val : grid[i]) {
if (val > m1) {m2 = m1; m1 = val;}
else if (val > m2) {m2 = val;}
}
stats[i] = {m1, m2};
}
vector<vector<vvll>> dp(2, vector<vvll>(2 * n));
for (int i = 0; i <= n; ++i) {
dp[0][i].resize(n + i - 1, vll(n + i - 1, 0));
dp[1][i].resize(n + i - 1, vll(n + i - 1, 0));
}
for (int i = n + 1; i < 2 * n; ++i) {
dp[0][i].resize(2 * n - 1 - (i - n), vll(2 * n - 1 - (i - n), 0));
dp[1][i].resize(2 * n - 1 - (i - n), vll(2 * n - 1 - (i - n), 0));
}
for (int t = 0; t < 2; ++t) {
for (int i = 1; i < 2 * n; ++i) {
int curr_sz = dp[0][i].size();
int prev_sz = dp[0][i - 1].size();
for (int j = 0; j < curr_sz; ++j) {
for (int k = j + 1; k < curr_sz; ++k) {
int a, b, c, d;
ll s = 0;
if (i <= n) {a = j - 1; b = j; c = k - 1; d = k;}
else {a = j; b = j + 1; c = k; d = k + 1;}
if (a >= 0) {
if (c > a) {
s = max(s, dp[t][i - 1][a][c]);
}
if (a < d && d < prev_sz) {
s = max(s, dp[t][i - 1][a][d]);
}
}
if (b < prev_sz) {
if (c > b) {
s = max(s, dp[t][i - 1][b][c]);
}
if (b < d && d < prev_sz) {
s = max(s, dp[t][i - 1][b][d]);
}
}
dp[t][i][j][k] = max(dp[t][i][j][k], s + grid[i - 1][j] + grid[i - 1][k]);
if (t == 0) {
if (stats[i - 1].first != grid[i - 1][k])
dp[1][i][j][k] = max(dp[1][i][j][k], s + stats[i - 1].first + grid[i - 1][k]);
else
dp[1][i][j][k] = max(dp[1][i][j][k], s + stats[i - 1].second + grid[i - 1][k]);
if (stats[i - 1].first != grid[i - 1][j])
dp[1][i][j][k] = max(dp[1][i][j][k], s + stats[i - 1].first + grid[i - 1][j]);
else
dp[1][i][j][k] = max(dp[1][i][j][k], s + stats[i - 1].second + grid[i - 1][j]);
}
}
}
}
}
ll ans = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
ans = max({ans, dp[0][2 * n - 1][i][j], dp[1][2 * n - 1][i][j]});
}
}
cout << ans << '\n';
}
int main() {
set_io();
int n, k;
cin >> n >> k;
vvi grid(2 * n - 1);
for (int i = 0; i < n; ++i) {
read_vector(grid[i], n + i);
}
for (int i = n; i < 2 * n - 1; ++i) {
read_vector(grid[i], 2 * n - 2 - (i - n));
}
if (k == 1) {
sub1(grid);
} else {
sub2(grid);
}
}