/*
* Copyright (c) 2024 Emon Thakur
* All rights reserved.
*/
#include<bits/stdc++.h>
using namespace std;
struct DSU{
int par[2005],sz[2005];
void create(int u)
{
par[u] = u;
sz[u]=1;
}
int findpar(int u)
{
if(par[u]==u) return u;
return par[u] = findpar(par[u]);
}
void Union(int u,int v)
{
int a = findpar(u);
int b = findpar(v);
if(sz[a] < sz[b]) swap(a,b);
par[b] = a;
sz[a] += b;
}
}dsu;
bool cmp(vector<int>&a,vector<int>&b) {return a>b;}
int main()
{
ios::sync_with_stdio(false); cin.tie(nullptr);
int n,k; cin >> n >> k;
int a[n][k];
for(int i=0;i<n;i++)
{
for(int j=0;j<k;j++) cin >> a[i][j];
}
if(n==1)
{
cout<<0<<endl;
return 0;
}
priority_queue<vector<int>>pq;
//vector<vector<int>> pq(0,vector<int>(3));
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
int cost = 0;
for(int m=0;m<k;m++) cost += abs(a[i][m]-a[j][m]);
pq.push({cost,i,j});
}
}
//sort(pq.begin(),pq.end(),cmp);
int need = n-2;
vector<int> x = pq.top(); pq.pop();
long long ans = x[0];
int taken[n+1]={0};
for(int i=1;i<=n;i++) dsu.create(i);
dsu.Union(x[1],x[2]);
taken[x[1]]=1;
taken[x[2]]=1;
int edge = 1,ind = 1;
while(edge != n-1)
{
x = pq.top(); pq.pop();
if(taken[x[1]] && taken[x[2]] && dsu.findpar(x[1])==dsu.findpar(x[2])) continue;
taken[x[1]]=1; taken[x[2]]=1;
dsu.Union(x[1],x[2]);
++edge;
ans += x[0];
}
cout << ans << endl;
}