using static IO;
public class IO {
public static IO Cin = new();
public static StreamReader reader = new(Console.OpenStandardInput());
public static StreamWriter writer = new(Console.OpenStandardOutput());
public static implicit operator string(IO _) => reader.ReadLine();
public static implicit operator char[](IO _) => reader.ReadLine().ToArray();
public static implicit operator int(IO _) => int.Parse(reader.ReadLine());
public static implicit operator double(IO _) => double.Parse(reader.ReadLine());
public static implicit operator string[](IO _) => reader.ReadLine().Split();
public static implicit operator int[](IO _) => Array.ConvertAll(reader.ReadLine().Split(), int.Parse);
public void Deconstruct(out int a, out int b) { int[] r = Cin; (a, b) = (r[0], r[1]); }
public void Deconstruct(out int a, out int b, out int c) { int[] r = Cin; (a, b, c) = (r[0], r[1], r[2]); }
public static IEnumerable<int> MakeRange(int start, int count) => Enumerable.Range(start, count);
public static T[] MakeArray<T>(int count) where T : new() => MakeRange(0, count).Select(_ => new T()).ToArray();
public static object? Cout { set { writer.Write(value); } }
public static object? Coutln { set { writer.WriteLine(value); } }
public static void Main() { Program.Coding(); writer.Flush(); }
}
class Program {
record struct Point(ushort X, ushort Y) {
public readonly int GetIndex(int n) => Y * n + X;
}
public static void Coding() {
checked {
(int n, int blind) = Cin;
int source = n * n;
int limiter = source + 1;
int sink = limiter + 1;
int[][] eggs = MakeRange(0, n).Select(_ => (int[])Cin).ToArray();
PriorityQueue<(Point a, Point b), int> candidate = new();
for (ushort y = 0; y < n; y++) {
for (ushort x = 1; x < n; x++) {
candidate.Enqueue((new((ushort)(x - 1), y), new(x, y)), eggs[y][x - 1] + eggs[y][x]);
if (candidate.Count > 64) candidate.Dequeue();
}
}
for (ushort x = 0; x < n; x++) {
for (ushort y = 1; y < n; y++) {
candidate.Enqueue((new(x, (ushort)(y - 1)), new(x, y)), eggs[y - 1][x] + eggs[y][x]);
if (candidate.Count > 64) candidate.Dequeue();
}
}
FlowGraph graph = new(sink + 1);
HashSet<int> used = new();
while (candidate.Count > 0) {
var (a, b) = candidate.Dequeue();
if ((a.X + a.Y) % 2 is not 0) (a, b) = (b, a);
int ai = a.GetIndex(n);
int bi = b.GetIndex(n);
graph.AddLine(ai, bi, 1, 0);
used.Add(ai);
used.Add(bi);
}
long sum = 0;
for (int y = 0; y < n; y++) {
for (int x = 0; x < n; x++) {
int unfresh = eggs[y][x];
sum += unfresh;
int me = y * n + x;
if (used.Contains(me) is false) continue;
if ((x + y) % 2 is 0) {
graph.AddLine(limiter, me, 1, -unfresh);
}
else {
graph.AddLine(me, sink, 1, -unfresh);
}
}
}
graph.AddLine(source, limiter, blind, 0);
_ = graph.GetMaxFlow(source, sink, out int cost);
Cout = sum + cost;
}
}
}
class FlowLine {
public int Start { get; }
public int End { get; }
public int Capacity { get; }
public int Flow { get; set; } = 0;
public FlowLine Reverse { get; }
public int Remaining => Capacity - Flow;
public int Cost { get; }
public FlowLine(int start, int end, int capacity, int cost, FlowLine? reverse = null) {
this.Start = start;
this.End = end;
this.Capacity = capacity;
this.Cost = cost;
this.Reverse = reverse ?? new(end, start, 0, -cost, this);
}
}
class FlowGraph {
public FlowGraph(int size) {
graph = MakeArray<List<FlowLine>>(Count = size);
}
public void AddLine(int start, int end, int capacity, int cost) {
FlowLine line = new(start, end, capacity, cost);
graph[start].Add(line);
graph[end].Add(line.Reverse);
}
public int GetMaxFlow(int source, int sink, out int cost) {
int totalFlow = 0;
for (cost = 0; true;) {
FlowLine?[] path = new FlowLine?[Count];
int[] dist = Enumerable.Repeat(int.MaxValue, Count).ToArray();
bool[] inQueue = new bool[Count];
Queue<int> queue = new();
dist[source] = 0;
inQueue[source] = true;
queue.Enqueue(source);
while (queue.Count > 0) {
int node = queue.Dequeue();
inQueue[node] = false;
foreach (var line in graph[node]) {
int nextdist = dist[node] + line.Cost;
if (line.Remaining > 0 && dist[line.End] > nextdist) {
dist[line.End] = nextdist;
path[line.End] = line;
if (inQueue[line.End] is false) {
inQueue[line.End] = true;
queue.Enqueue(line.End);
}
}
}
}
if (path[sink] is not FlowLine sinkLine) break;
int flow = int.MaxValue;
for (FlowLine? line = sinkLine; line is not null; line = path[line.Start]) {
flow = Math.Min(flow, line.Remaining);
}
for (FlowLine? line = sinkLine; line is not null; line = path[line.Start]) {
line.Flow += flow;
line.Reverse.Flow -= flow;
cost += flow * line.Cost;
}
totalFlow += flow;
}
return totalFlow;
}
public int Count { get; }
private readonly List<FlowLine>[] graph;
}