/*洛谷 U4792 Acheing 二维线段树 n*n*logn*logn T成傻逼2333 */
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1010
#define lc k*2
#define rc k*2+1
#define mid (l+r)/2
using namespace std;
int n,m,k,g[maxn][maxn],x,y,z;
int x1,x2,y1,y2,ans=0x7fffffff;
int mx[maxn*4][maxn*4],mxx[maxn*4][maxn*4];
void Insert_y(int kx,int k,int l,int r){
mx[kx][k]=min(mx[kx][k],z);
mxx[kx][k]=max(mxx[kx][k],z);
if(l==r)return;
if(y<=mid)Insert_y(kx,lc,l,mid);
else Insert_y(kx,rc,mid+1,r);
mx[kx][k]=min(mx[kx][lc],mx[kx][rc]);
mxx[kx][k]=max(mxx[kx][lc],mxx[kx][rc]);
}
void Insert_x(int k,int l,int r){
Insert_y(k,1,1,m);
if(l==r)return;
if(x<=mid)Insert_x(lc,l,mid);
else Insert_x(rc,mid+1,r);
}
int Query_miny(int kx,int k,int l,int r){
if(y1<=l&&y2>=r)return mx[kx][k];
if(y2<=mid)return Query_miny(kx,lc,l,mid);
else if(y1>mid)return Query_miny(kx,rc,mid+1,r);
else return min(Query_miny(kx,lc,l,mid),Query_miny(kx,rc,mid+1,r));
}
int Query_maxy(int kx,int k,int l,int r){
if(y1<=l&&y2>=r)return mxx[kx][k];
if(y2<=mid)return Query_maxy(kx,lc,l,mid);
else if(y1>mid)return Query_maxy(kx,rc,mid+1,r);
else return max(Query_maxy(kx,lc,l,mid),Query_maxy(kx,rc,mid+1,r));
}
int Query_minx(int k,int l,int r){
if(x1<=l&&x2>=r)return Query_miny(k,1,1,m);
if(x2<=mid)return Query_minx(lc,l,mid);
else if(x1>mid)return Query_minx(rc,mid+1,r);
else return min(Query_minx(lc,l,mid),Query_minx(rc,mid+1,r));
}
int Query_maxx(int k,int l,int r){
if(x1<=l&&x2>=r)return Query_maxy(k,1,1,m);
if(x2<=mid)return Query_maxx(lc,l,mid);
else if(x1>mid)return Query_maxx(rc,mid+1,r);
else return max(Query_maxx(lc,l,mid),Query_maxx(rc,mid+1,r));
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
memset(mxx,-127/3,sizeof(mxx));
memset(mx,127/3,sizeof(mx));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&g[i][j]);
x=i;y=j;z=g[i][j];
Insert_x(1,1,n);
}
for(int i=k;i<=n;i++)
for(int j=k;j<=m;j++){
x1=i-k+1;x2=i;y1=j-k+1;y2=j;
int minner=Query_minx(1,1,n);
int maxxer=Query_maxx(1,1,n);
ans=min(ans,maxxer-minner);
}
printf("%d\n",ans);
return 0;
}
/*洛谷 U4792 Acheing 单调队列运用 解决二维线段树超时的问题 */
#include<cstdio>
#include<cstring>
#define maxn 1010
using namespace std;
int n,m,k,g[maxn][maxn],mx[maxn][maxn],mi[maxn][maxn],mxx[maxn][maxn],mxi[maxn][maxn];
int q[maxn],head,tail,ans=0x7fffffff;
int init(){
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
int min(int x,int y){
return x<y?x:y;
}
void Ready(){
for(int j=1;j<=m;j++){
head=1;tail=0;
for(int i=1;i<=n;i++){
int x=g[i][j];
while(head<=tail&&x>g[q[tail]][j])tail--;
q[++tail]=i;
if(i-q[head]>=k)head++;
mx[i][j]=g[q[head]][j];
}
}
for(int j=1;j<=m;j++){
head=1;tail=0;
for(int i=1;i<=n;i++){
int x=g[i][j];
while(head<=tail&&x<g[q[tail]][j])tail--;
q[++tail]=i;
if(i-q[head]>=k)head++;
mi[i][j]=g[q[head]][j];
}
}
}
void Solve(){
for(int i=k;i<=n;i++){
head=1;tail=0;
for(int j=1;j<=m;j++){
int x=mx[i][j];
while(head<=tail&&x>mx[i][q[tail]])tail--;
q[++tail]=j;
if(j-q[head]>=k)head++;
mxx[i][j]=mx[i][q[head]];
}
}
for(int i=k;i<=n;i++){
head=1;tail=0;
for(int j=1;j<=m;j++){
int x=mi[i][j];
while(head<=tail&&x<mi[i][q[tail]])tail--;
q[++tail]=j;
if(j-q[head]>=k)head++;
mxi[i][j]=mi[i][q[head]];
}
}
}
int main()
{
n=init();m=init();k=init();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
g[i][j]=init();
Ready();Solve();
for(int i=k;i<=n;i++)
for(int j=k;j<=m;j++)
ans=min(ans,mxx[i][j]-mxi[i][j]);
printf("%d\n",ans);
return 0;
}