#include<bits/stdc++.h>
using namespace std;
const int N=13;
int mp[N][N],flag,n,k;
bool vis[N][N];
int f[N][N][N][N];//存储路径,用于判断是否斜着走,是本题剪枝的难点
vector<int>ans;
vector<int>res;
int dx[]={-1,-1,0,1,1,1,0,-1};
int dy[]={0,1,1,1,0,-1,-1,-1};bool check1(int x,int y){//坐标合法return x>=1&&x<=n&&y>=1&&y<=n;
}bool check2(int x,int y,int i){//检查是否斜着走if(i==0||i==2||i==4||i==6) return true;if(i==1&&(f[x-1][y][x][y+1]||f[x][y+1][x-1][y])) return false;if(i==3&&(f[x][y+1][x+1][y]||f[x+1][y][x][y+1])) return false;if(i==5&&(f[x][y-1][x+1][y]||f[x+1][y][x][y-1])) return false;if(i==7&&(f[x][y-1][x-1][y]||f[x-1][y][x][y-1])) return false;return true;
}void dfs(int x,int y,int cnt){//传过来的坐标一定合法、未访问等,line38剪去了不合法的情况if(flag) return ;//找到答案时,统统直接返回,也算是剪枝,节省时间/*事实上,走到n,n一定可以返回了,也算是种剪枝*/if(x==n&&y==n&&cnt==n*n){//走到(n,n)如果有解的话,以一个解即答案(字典序最小)res=ans;flag=1;return ;}vis[x][y]=1;for(int i=0;i<8;i++){int nx=x+dx[i];int ny=y+dy[i];//剪枝if(!check1(nx,ny)||vis[nx][ny]) continue;if((mp[x][y]+1)%k!=mp[nx][ny]) continue;if(!check2(x,y,i)) continue;f[x][y][nx][ny]=f[nx][ny][x][y]=1;ans.push_back(i);dfs(nx,ny,cnt+1);//回溯f[x][y][nx][ny]=f[nx][ny][x][y]=0;vis[nx][ny]=0;ans.pop_back();}
}signed main()
{cin>>n>>k;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)cin>>mp[i][j];}dfs(1,1,1);if(flag)for(auto i:res)cout<<i;elsecout<<-1;
}
25/2/18