#include <bits/stdc++.h>
#define REP(a,b) for(int a=0; a<(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define x first
#define y second
#define pb push_back
#define re real()
#define im imag()

using namespace std;

typedef pair<int, int> PII;

int n, m, a, b;
int tmp[33][33];
int source[33][33];
int target[33][33];
PII prv[33][33];
bool block[33][33];
vector<PII> R;

int dx[] = {-1,-1,-1,0,0,1,1,1};
int dy[] = {-1,0,1,-1,1,-1,0,1};

void save(){
	FWD(i,0,n) FWD(j,0,m) tmp[i][j] = source[i][j];
}

void load(){
	R.clear();
	FWD(i,0,n) FWD(j,0,m) source[i][j] = tmp[i][j];
}

void check(){
	FWD(i,0,n) FWD(j,0,m) if(source[i][j] != target[i][j]) return;
	printf("%d\n", (int)R.size()-1);
	for(int i=0;i<R.size();++i)printf("%d %d\n", R[i].x+1, R[i].y+1);
	exit(0);
}

void make(int x, int y){
	swap(source[R.back().x][R.back().y], source[x][y]);
	R.push_back(PII(x,y));
	a = x; b = y;
}

bool in(int x, int y){
	return 0 <= x && x < n && 0 <= y && y < m && !block[x][y];
}

void path(int x, int y){
	FWD(i,0,n) FWD(j,0,m) prv[i][j] = PII(-1,-1);
	queue<PII> Q;
	Q.push(PII(a,b));
	PII c = PII(x, y);
	while(!Q.empty()){
		x = Q.front().x;
		y = Q.front().y;
		Q.pop();
		FWD(d,0,8){
			int nx = x+dx[d]; int ny = y+dy[d];
			if(in(nx, ny) && prv[nx][ny] == PII(-1,-1)){
				prv[nx][ny] = PII(x,y);
				Q.push(PII(nx, ny));
			}
		}
	}
	stack<PII> S;
	while(c != PII(a,b)){
		S.push(c);
		c = prv[c.x][c.y];
	}
	while(!S.empty()){
		make(S.top().x, S.top().y);
		S.pop();
	}
}

void setp(int i, int j){
	path(i, j);
	PII s = PII(i,j);
	block[i][j] = 1;
	FWD(p,0,n) FWD(q,0,m) if(!block[p][q] && source[p][q] == target[i][j]) s = PII(p,q);
	block[i][j] = 0;
	if(s == PII(i,j)){
		printf("-1\n");
		exit(0);
	}
	for(;;){
		path(s.x, s.y);
		s = R[R.size()-2];
		if(PII(i,j) == s) break;
		block[s.x][s.y] = 1;
		path(i, j);
		block[s.x][s.y] = 0;
	}
	block[i][j] = 1;
}

int main(){
	scanf("%d %d", &n, &m);
	FWD(i,0,n) FWD(j,0,m) scanf("%d", &source[i][j]);
	FWD(i,0,n) FWD(j,0,m) scanf("%d", &target[i][j]);
	save();
	if(n == 1 || m == 1){
		FWD(s,0,max(n,m)){
			for(int d=-1; d<=1; d+=2){
				load();
				R.push_back(PII(n==1?0:s,n==1?s:0));
				for(int i=s+d;-1<i&&i<max(n,m);i+=d){
					make(n==1?0:i,n==1?i:0);
					check();
				}
			}
		}
		printf("-1\n");
		return 0;
	}
	FWD(i,0,n) FWD(j,0,m) if(source[i][j] == target[n-1][m-1]) a = i, b = j;
	R.push_back(PII(a,b));
	FWD(i,0,n-2)
		FWD(j,0,m)
			setp(i, j);
	FWD(j,0,m-1){
		setp(n-2,j);
		setp(n-1,j);
	}
	check();
	if(a == n-1)
		make(n-2, m-1);
	else
		make(n-1, m-1);
	check();
	printf("-1\n");
	return 0;
}


#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
#define x first
#define y second
#define mp make_pair
#define pb push_back

void open()
{
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
}

int dx[8]={-1, 0, 1,-1,0,1,-1,1};
int dy[8]={-1,-1,-1,1, 1,1,0, 0};

class chess
{
	public:
		int ori[33][33],end[33][33],mid[33][33],m,n,a,b,num[2][901];
		bool use[33][33];pii pre[33][33];
		vector<pii> ans;
		void work()
		{
			read();
			all_judge();
			pre_judge();
			if(min(n,m)==1)work1();
			top_judge();
		}
	private:
		void read()
		{
			cin>>n>>m;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>ori[i][j];
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>end[i][j];
		}
		bool all_judge()
		{
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)++num[0][ori[i][j]],++num[1][end[i][j]];
			for(int i=1;i<=900;++i)if(num[0][i]!=num[1][i]){printf("-1\n");exit(0);}
		}
		bool pre_judge()
		{
			for(int i=1;i<=n;++i)
				for(int j=1;j<=m;++j)
					if(ori[i][j]!=end[i][j])return 0;
			printf("0\n");
			exit(0);
		}
		inline pii wr(pii x){printf("%d %d\n",x.x,x.y);return x;}
		inline void print(){printf("%d\n",ans.size()-1);for(int i=0;i<ans.size();++i)wr(ans[i]);exit(0);}
		inline bool judge(){for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(mid[i][j]!=end[i][j])return 0;print();}
		//inline void save(){for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)mid[i][j]=ori[i][j];}
		inline void load(){ans.clear();for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)mid[i][j]=ori[i][j];}
		inline bool in(int x,int y){return 1<=x && x<=n && 1<=y && y<=m && !use[x][y];}
		inline void exch(int x,int y)
		{
			swap(mid[ans.back().x][ans.back().y],mid[x][y]);
			ans.pb(mp(x,y));a=x;b=y;
		}
		void work1()
		{
			for(int i=1;i<=max(m,n);++i)
				for(int d=-1;d<2;d+=2)
				{
					load();ans.pb(mp(n==1 ? 1 : i,n==1 ? i : 1));
					for(int k=i+d;1<=k && k<=max(m,n);k+=d)
					{
						exch(n==1 ? 1 : k,n==1 ? k : 1);
						judge();
					}
				}
				printf("-1\n");exit(0);
		}
		void way_to(int x,int y)
		{
			//cout<<x<<" "<<y<<endl;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)pre[i][j]=mp(-1,-1);
			queue<pii> q;pii u;
			while(!q.empty())q.pop();
			q.push(mp(a,b));
			while(!q.empty())
			{
				u=q.front();q.pop();
				for(int d=0;d<8;++d)
					if(in(u.x+dx[d],u.y+dy[d]) && pre[u.x+dx[d]][u.y+dy[d]]==mp(-1,-1))
					{
						pre[u.x+dx[d]][u.y+dy[d]]=u;
						q.push(mp(u.x+dx[d],u.y+dy[d]));
					}
			}
			stack<pii> s;
			while(!s.empty())s.pop();
			pii l=mp(x,y);
			while(l!=mp(a,b)){s.push(l);l=pre[l.x][l.y];}
			while(!s.empty()){exch(s.top().x,s.top().y);s.pop();}
		}
		void access(int x,int y)
		{
			way_to(x,y);
			pii s=mp(x,y);
			use[x][y]=1;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(!use[i][j] && mid[i][j]==end[x][y])s=mp(i,j);
			use[x][y]=0;
			//wr(s);
			if(s==mp(x,y)){printf("-1\n");exit(0);}
			//cout<<"11"<<endl;
			for(;;)
			{
				way_to(s.x,s.y);
				s=ans[ans.size()-2];
				if(mp(x,y)==s)break;
				use[s.x][s.y]=1;way_to(x,y);use[s.x][s.y]=0;
			}
			use[x][y]=1;
		}
		void test()
		{
			for(int i=1;i<=n;++i,cout<<endl)for(int j=1;j<=m;++j)cout<<mid[i][j]<<' ';
		}
		void top_judge()
		{
			load();
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(ori[i][j]==end[n][m])a=i,b=j;
			ans.pb(mp(a,b));
			for(int i=1;i<=n-2;++i)for(int j=1;j<=m;++j)access(i,j);
			//return;
			for(int i=1;i<=m-1;++i)access(n-1,i),access(n,i);
			//test();
			judge();
			if(a==n-1)access(n,m);else access(n-1,m);
			judge();
			printf("-1\n");return;
		}
}node;

int main()
{
	//open();
	node.work();
}


#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
#define x first
#define y second
#define mp make_pair
#define pb push_back

void open()
{
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
}

int dx[8]={-1, 0, 1,-1,0,1,-1,1};
int dy[8]={-1,-1,-1,1, 1,1,0, 0};

class chess
{
	public:
		int ori[33][33],end[33][33],mid[33][33],m,n,a,b,num[2][901];
		bool use[33][33];pii pre[33][33];
		vector<pii> ans;
		void work()
		{
			read();
			all_judge();
			pre_judge();
			if(min(n,m)==1)work1();
			top_judge();
		}
	private:
		void read()
		{
			cin>>n>>m;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>ori[i][j];
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>end[i][j];
		}
		bool all_judge()
		{
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)++num[0][ori[i][j]],++num[1][end[i][j]];
			for(int i=1;i<=900;++i)if(num[0][i]!=num[1][i]){printf("-1\n");exit(0);}
		}
		bool pre_judge()
		{
			for(int i=1;i<=n;++i)
				for(int j=1;j<=m;++j)
					if(ori[i][j]!=end[i][j])return 0;
			printf("0\n");
			exit(0);
		}
		inline pii wr(pii x){printf("%d %d\n",x.x,x.y);return x;}
		inline void print(){printf("%d\n",ans.size()-1);for(int i=0;i<ans.size();++i)wr(ans[i]);exit(0);}
		inline bool judge(){for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(mid[i][j]!=end[i][j])return 0;print();}
		//inline void save(){for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)mid[i][j]=ori[i][j];}
		inline void load(){ans.clear();for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)mid[i][j]=ori[i][j];}
		inline bool in(int x,int y){return 1<=x && x<=n && 1<=y && y<=m && !use[x][y];}
		inline void exch(int x,int y)
		{
			swap(mid[ans.back().x][ans.back().y],mid[x][y]);
			ans.pb(mp(x,y));a=x;b=y;
		}
		void work1()
		{
			for(int i=1;i<=max(m,n);++i)
				for(int d=-1;d<2;d+=2)
				{
					load();ans.pb(mp(n==1 ? 1 : i,n==1 ? i : 1));
					for(int k=1;1<=k && k<=max(m,n);k+=d)
					{
						exch(n==1 ? 1 : k,n==1 ? k : 1);
						judge();
					}
				}
				printf("-1\n");exit(0);
		}
		void way_to(int x,int y)
		{
			//cout<<x<<" "<<y<<endl;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)pre[i][j]=mp(-1,-1);
			queue<pii> q;pii u;
			while(!q.empty())q.pop();
			q.push(mp(a,b));
			while(!q.empty())
			{
				u=q.front();q.pop();
				for(int d=0;d<8;++d)
					if(in(u.x+dx[d],u.y+dy[d]) && pre[u.x+dx[d]][u.y+dy[d]]==mp(-1,-1))
					{
						pre[u.x+dx[d]][u.y+dy[d]]=u;
						q.push(mp(u.x+dx[d],u.y+dy[d]));
					}
			}
			stack<pii> s;
			while(!s.empty())s.pop();
			pii l=mp(x,y);
			while(l!=mp(a,b)){s.push(l);l=pre[l.x][l.y];}
			while(!s.empty()){exch(s.top().x,s.top().y);s.pop();}
		}
		void access(int x,int y)
		{
			way_to(x,y);
			pii s=mp(x,y);
			use[x][y]=1;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(!use[i][j] && mid[i][j]==end[x][y])s=mp(i,j);
			//wr(s);
			if(s==mp(x,y)){printf("-1\n");exit(0);}
			//cout<<"11"<<endl;
			for(;;)
			{
				way_to(s.x,s.y);
				s=ans[ans.size()-2];
				if(mp(x,y)==s)break;
				use[s.x][s.y]=1;way_to(x,y);use[s.x][s.y]=0;
			}
			use[x][y]=1;
		}
		void test()
		{
			for(int i=1;i<=n;++i,cout<<endl)for(int j=1;j<=m;++j)cout<<mid[i][j]<<' ';
		}
		void top_judge()
		{
			load();
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(ori[i][j]==end[n][m])a=i,b=j;
			ans.pb(mp(a,b));
			for(int i=1;i<=n-2;++i)for(int j=1;j<=m;++j)access(i,j);
			for(int i=1;i<=m-1;++i)access(n-1,i),access(n,i);
			//test();
			judge();
			if(a==n-1)access(n,m);else access(n-1,m);
			judge();
			printf("-1\n");return;
		}
}node;

int main()
{
	open();
	node.work();
}


#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
#define x first
#define y second
#define mp make_pair
#define pb push_back

void open()
{
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
}

int dx[8]={-1, 0, 1,-1,0,1,-1,1};
int dy[8]={-1,-1,-1,1, 1,1,0, 0};

class chess
{
	public:
		int ori[33][33],end[33][33],mid[33][33],m,n,a,b,num[2][901];
		bool use[33][33];pii pre[33][33];
		vector<pii> ans;
		void work()
		{
			read();
			all_judge();
			pre_judge();
			if(min(n,m)==1)work1();
			top_judge();
		}
	private:
		void read()
		{
			cin>>n>>m;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>ori[i][j];
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>end[i][j];
		}
		bool all_judge()
		{
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)++num[0][ori[i][j]],++num[1][end[i][j]];
			for(int i=1;i<=900;++i)if(num[0][i]!=num[1][i]){printf("-1\n");exit(0);}
		}
		bool pre_judge()
		{
			for(int i=1;i<=n;++i)
				for(int j=1;j<=m;++j)
					if(ori[i][j]!=end[i][j])return 0;
			printf("0\n");
			exit(0);
		}
		inline pii wr(pii x){printf("%d %d\n",x.x,x.y);return x;}
		inline void print(){printf("%d\n",ans.size()-1);for(int i=0;i<ans.size();++i)wr(ans[i]);exit(0);}
		inline bool judge(){for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(mid[i][j]!=end[i][j])return 0;print();}
		inline void load(){ans.clear();for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)mid[i][j]=ori[i][j];}
		inline bool in(int x,int y){return 1<=x && x<=n && 1<=y && y<=m && !use[x][y];}
		inline void exch(int x,int y)
		{
			swap(mid[ans.back().x][ans.back().y],mid[x][y]);
			ans.pb(mp(x,y));a=x;b=y;
		}
		void work1()
		{
			for(int i=1;i<=max(m,n);++i)
				for(int d=-1;d<2;d+=2)
				{
					load();ans.pb(mp(n==1 ? 1 : i,n==1 ? i : 1));
					for(int k=i+d;1<=k && k<=max(m,n);k+=d)
					{
						exch(n==1 ? 1 : k,n==1 ? k : 1);
						judge();
					}
				}
				printf("-1\n");exit(0);
		}
		void way_to(int x,int y)
		{
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)pre[i][j]=mp(-1,-1);
			queue<pii> q;pii u;
			while(!q.empty())q.pop();
			q.push(mp(a,b));
			while(!q.empty())
			{
				u=q.front();q.pop();
				for(int d=0;d<8;++d)
					if(in(u.x+dx[d],u.y+dy[d]) && pre[u.x+dx[d]][u.y+dy[d]]==mp(-1,-1))
					{
						pre[u.x+dx[d]][u.y+dy[d]]=u;
						q.push(mp(u.x+dx[d],u.y+dy[d]));
					}
			}
			stack<pii> s;
			while(!s.empty())s.pop();
			pii l=mp(x,y);
			while(l!=mp(a,b)){s.push(l);l=pre[l.x][l.y];}
			while(!s.empty()){exch(s.top().x,s.top().y);s.pop();}
		}
		void access(int x,int y)
		{
			way_to(x,y);
			pii s=mp(x,y);
			use[x][y]=1;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(!use[i][j] && mid[i][j]==end[x][y])s=mp(i,j);
			use[x][y]=0;
			if(s==mp(x,y)){printf("-1\n");exit(0);}
			for(;;)
			{
				way_to(s.x,s.y);
				s=ans[ans.size()-2];
				if(mp(x,y)==s)break;
				use[s.x][s.y]=1;way_to(x,y);use[s.x][s.y]=0;
			}
			use[x][y]=1;
		}
		void test(){for(int i=1;i<=n;++i,cout<<endl)for(int j=1;j<=m;++j)cout<<mid[i][j]<<' ';}
		void top_judge()
		{
			load();
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(ori[i][j]==end[n][m])a=i,b=j;
			ans.pb(mp(a,b));
			for(int i=1;i<=n-2;++i)for(int j=1;j<=m;++j)access(i,j);
			for(int i=1;i<=m-1;++i)access(n-1,i),access(n,i);
			test();judge();
			if(a==n-1)exch(n,m);else exch(n-1,m);
			judge();
			printf("-1\n");return;
		}
}node;

int main()
{
	//open();
	node.work();
}


#include <bits/stdc++.h>
#define REP(a,b) for(int a=0; a<(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define BCK(a,b,c) for(int a=(b); a>(c); --a)
#define x first
#define y second
#define pb push_back
#define re real()
#define im imag()

using namespace std;

typedef pair<int, int> PII;

int n, m, a, b;
int tmp[33][33];
int source[33][33];
int target[33][33];
PII prv[33][33];
bool block[33][33];
vector<PII> R;

int dx[] = {-1,-1,-1,0,0,1,1,1};
int dy[] = {-1,0,1,-1,1,-1,0,1};

void save(){
	FWD(i,0,n) FWD(j,0,m) tmp[i][j] = source[i][j];
}

void load(){
	R.clear();
	FWD(i,0,n) FWD(j,0,m) source[i][j] = tmp[i][j];
}

void check(){
	FWD(i,0,n) FWD(j,0,m) if(source[i][j] != target[i][j]) return;
	printf("%d\n", (int)R.size()-1);
	for(PII r : R) printf("%d %d\n", r.x+1, r.y+1);
	exit(0);
}

void make(int x, int y){
	swap(source[R.back().x][R.back().y], source[x][y]);
	R.push_back(PII(x,y));
	a = x; b = y;
}

bool in(int x, int y){
	return 0 <= x && x < n && 0 <= y && y < m && !block[x][y];
}

void path(int x, int y){
	FWD(i,0,n) FWD(j,0,m) prv[i][j] = PII(-1,-1);
	queue<PII> Q;
	Q.push(PII(a,b));
	PII c = PII(x, y);
	while(!Q.empty()){
		x = Q.front().x;
		y = Q.front().y;
		Q.pop();
		FWD(d,0,8){
			int nx = x+dx[d]; int ny = y+dy[d];
			if(in(nx, ny) && prv[nx][ny] == PII(-1,-1)){
				prv[nx][ny] = PII(x,y);
				Q.push(PII(nx, ny));
			}
		}
	}
	stack<PII> S;
	while(c != PII(a,b)){
		S.push(c);
		c = prv[c.x][c.y];
	}
	while(!S.empty()){
		make(S.top().x, S.top().y);
		S.pop();
	}
}

void setp(int i, int j){
	path(i, j);
	PII s = PII(i,j);
	block[i][j] = 1;
	FWD(p,0,n) FWD(q,0,m) if(!block[p][q] && source[p][q] == target[i][j]) s = PII(p,q);
	block[i][j] = 0;
	if(s == PII(i,j)){
		printf("-1\n");
		exit(0);
	}
	for(;;){
		path(s.x, s.y);
		s = R[R.size()-2];
		if(PII(i,j) == s) break;
		block[s.x][s.y] = 1;
		path(i, j);
		block[s.x][s.y] = 0;
	}
	block[i][j] = 1;
}

int main(){
	scanf("%d %d", &n, &m);
	FWD(i,0,n) FWD(j,0,m) scanf("%d", &source[i][j]);
	FWD(i,0,n) FWD(j,0,m) scanf("%d", &target[i][j]);
	save();
	if(n == 1 || m == 1){
		FWD(s,0,max(n,m)){
			for(int d=-1; d<=1; d+=2){
				load();
				R.push_back(PII(n==1?0:s,n==1?s:0));
				for(int i=s+d;-1<i&&i<max(n,m);i+=d){
					make(n==1?0:i,n==1?i:0);
					check();
				}
			}
		}
		printf("-1\n");
		return 0;
	}
	FWD(i,0,n) FWD(j,0,m) if(source[i][j] == target[n-1][m-1]) a = i, b = j;
	R.push_back(PII(a,b));
	FWD(i,0,n-2)
		FWD(j,0,m)
			setp(i, j);
	FWD(j,0,m-1){
		setp(n-2,j);
		setp(n-1,j);
	}
	check();
	if(a == n-1)
		make(n-2, m-1);
	else
		make(n-1, m-1);
	check();
	printf("-1\n");
	return 0;
}


#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
#define x first
#define y second
#define mp make_pair
#define pb push_back

void open()
{
	freopen("game.in","r",stdin);
	freopen("game.out","w",stdout);
}

int dx[8]={-1, 0, 1,-1,0,1,-1,1};
int dy[8]={-1,-1,-1,1, 1,1,0, 0};

class chess
{
	public:
		int ori[33][33],end[33][33],mid[33][33],m,n,a,b,num[2][901];
		bool use[33][33];pii pre[33][33];
		vector<pii> ans;
		void work()
		{
			read();
			all_judge();
			pre_judge();
			if(min(n,m)==1)work1();
			top_judge();
		}
	private:
		void read()
		{
			cin>>n>>m;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>ori[i][j];
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)cin>>end[i][j];
		}
		bool all_judge()
		{
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)++num[0][ori[i][j]],++num[1][end[i][j]];
			for(int i=1;i<=900;++i)if(num[0][i]!=num[1][i]){printf("-1\n");exit(0);}
		}
		bool pre_judge()
		{
			for(int i=1;i<=n;++i)
				for(int j=1;j<=m;++j)
					if(ori[i][j]!=end[i][j])return 0;
			printf("0\n");
			exit(0);
		}
		inline pii wr(pii x){printf("%d %d\n",x.x,x.y);return x;}
		inline void print(){printf("%d\n",ans.size()-1);for(int i=0;i<ans.size();++i)wr(ans[i]);exit(0);}
		inline bool judge(){for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(mid[i][j]!=end[i][j])return 0;print();}
		//inline void save(){for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)mid[i][j]=ori[i][j];}
		inline void load(){ans.clear();for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)mid[i][j]=ori[i][j];}
		inline bool in(int x,int y){return 1<=x && x<=n && 1<=y && y<=m && !use[x][y];}
		inline void exch(int x,int y)
		{
			swap(mid[ans.back().x][ans.back().y],mid[x][y]);
			ans.pb(mp(x,y));a=x;b=y;
		}
		void work1()
		{
			for(int i=1;i<=max(m,n);++i)
				for(int d=-1;d<2;d+=2)
				{
					load();ans.pb(mp(n==1 ? 1 : i,n==1 ? i : 1));
					for(int k=i+d;1<=k && k<=max(m,n);k+=d)
					{
						exch(n==1 ? 1 : k,n==1 ? k : 1);
						judge();
					}
				}
				printf("-1\n");exit(0);
		}
		void way_to(int x,int y)
		{
			//cout<<x<<" "<<y<<endl;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)pre[i][j]=mp(-1,-1);
			queue<pii> q;pii u;
			while(!q.empty())q.pop();
			q.push(mp(a,b));
			while(!q.empty())
			{
				u=q.front();q.pop();
				for(int d=0;d<8;++d)
					if(in(u.x+dx[d],u.y+dy[d]) && pre[u.x+dx[d]][u.y+dy[d]]==mp(-1,-1))
					{
						pre[u.x+dx[d]][u.y+dy[d]]=u;
						q.push(mp(u.x+dx[d],u.y+dy[d]));
					}
			}
			stack<pii> s;
			while(!s.empty())s.pop();
			pii l=mp(x,y);
			while(l!=mp(a,b)){s.push(l);l=pre[l.x][l.y];}
			while(!s.empty()){exch(s.top().x,s.top().y);s.pop();}
		}
		void access(int x,int y)
		{
			way_to(x,y);
			pii s=mp(x,y);
			use[x][y]=1;
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(!use[i][j] && mid[i][j]==end[x][y])s=mp(i,j);
			//wr(s);
			if(s==mp(x,y)){printf("-1\n");exit(0);}
			//cout<<"11"<<endl;
			for(;;)
			{
				way_to(s.x,s.y);
				s=ans[ans.size()-2];
				if(mp(x,y)==s)break;
				use[s.x][s.y]=1;way_to(x,y);use[s.x][s.y]=0;
			}
			use[x][y]=1;
		}
		void test()
		{
			for(int i=1;i<=n;++i,cout<<endl)for(int j=1;j<=m;++j)cout<<mid[i][j]<<' ';
		}
		void top_judge()
		{
			load();
			for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)if(ori[i][j]==end[n][m])a=i,b=j;
			ans.pb(mp(a,b));
			for(int i=1;i<=n-2;++i)for(int j=1;j<=m;++j)access(i,j);
			for(int i=1;i<=m-1;++i)access(n-1,i),access(n,i);
			//test();
			judge();
			if(a==n-1)access(n,m);else access(n-1,m);
			judge();
			printf("-1\n");return;
		}
}node;

int main()
{
	//open();
	node.work();
}


#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

struct Ball { int color,x,y,goX,goY;};

int n,m;
Ball balls[30][30];
Ball* c;
int A[30][30];
int tmp[30][30];
int B[30][30];
Ball* cur[30][30];
Ball* need[30][30];
vector<int> print;

void printgrid() {
    for (int i=0;i<n;i++) {
        for (int j=0;j<m;j++) printf("%d ",cur[i][j]->color);
        printf("\n");
    }
    printf("\n");
}

void go(int dx, int dy) {
    int x = c->x, y = c->y;
    int nx = x+dx, ny = y+dy;
    print.push_back(nx*m+ny);
    Ball* next = cur[nx][ny];
    swap(cur[x][y],cur[nx][ny]);
    c->x = nx, c->y = ny;
    next->x = x, next->y = y;
}

void solve1() {
    int ok = 0;
    for (int a=0;a<m && !ok;a++) {
        for (int b=0;b<m && !ok;b++) {
            print.clear();
            for (int i=0;i<m;i++) tmp[0][i] = A[0][i];
            int cur = a;
            print.push_back(cur);
            while (cur<b) swap(tmp[0][cur],tmp[0][cur+1]), cur+=1, print.push_back(cur);
            while (cur>b) swap(tmp[0][cur],tmp[0][cur-1]), cur-=1, print.push_back(cur);
            int good = 1;
            for (int i=0;i<m;i++) if (tmp[0][i]!=B[0][i]) good = 0;
            if (good) ok = 1;
        }
    }
    if (!ok) print.clear();
}

void getvert(Ball* which, int off) {
    if (c->x!=n-1) go(1,0);
    if (c->x==which->x) go(which->x==n-1 ? -1 : 1,0);
    while (c->y<which->y) go(0,1);
    while (c->y>which->y) go(0,-1);
    while (c->x<which->x+off) go(1,0);
    while (c->x>which->x+off) go(-1,0);
}

void solve() {
    for (int i=0;i<n;i++) for (int j=0;j<m;j++) {
        int found = 0;
        for (int a=0;a<n && !found;a++) for (int b=0;b<m && !found;b++) {
            if (cur[a][b]->goX==-1 && cur[a][b]->color==B[i][j]) {
                found = 1;
                cur[a][b]->goX = i; cur[a][b]->goY = j;
                need[i][j] = cur[a][b];
            }
        }
        if (found==0) return;
    }
    c = need[n-1][m-1];
    print.push_back(c->x*m+c->y);
    for (int i=0;i<n-2;i++) for (int j=0;j<m;j++) {
        if (need[i][j]->x==n-1) getvert(need[i][j],-1), go(1,0);
        else getvert(need[i][j],+1);
        while (c->y!=j) {
            int l = c->y>j;
            go(-1,l ? -1 : 1);
            go(0,l ? 1 : -1);
            go(1,l ? -1 : 1);
        }
        while (c->x>i+1) {
            int l = j>0;
            go(-1,l ? -1 : 1);
            go(-1,l ? 1 : -1);
            go(1,0);
        }
    }
    while (c->y>0) go(0,-1);
    if (c->x!=n-1) go(1,0);
    for (int j=0;j<m-2;j++) for (int i=n-2;i<n;i++) {
        if (need[i][j]->x==i && need[i][j]->y==j) {
            if (i==n-2) go(-1,1);
            else go(1,0);
            continue;
        }
        if (c->x==need[i][j]->x) go(c->x==n-1 ? -1 : 1,0);
        while (c->y<need[i][j]->y) go(0,1);
        if (need[i][j]->x!=i) go(c->x==n-1 ? -1 : 1,0);
        go(c->x==n-1 ? -1 : 1,-1);
        go(0,1);
        while (need[i][j]->y>j) {
            int d = c->x==n-1;
            go(d ? -1 : 1,-1);
            go(d ? 1 : -1,-1);
            go(0,1);
        }
    }
    if (need[n-2][m-2]->x!=n-2 || need[n-2][m-2]->y!=m-2) {
        go(-1,0);
        go(need[n-2][m-2]->x-c->x,need[n-2][m-2]->y-c->y);
        if (c->y==m-1) go(c->x==n-1 ? 0 : 1,-1);
    }
    if (need[n-1][m-2]->x!=n-1 || need[n-1][m-2]->y!=m-2) go(need[n-1][m-2]->x-c->x,need[n-1][m-2]->y-c->y);
    if (c->x!=n-1) go(1,0);
}

int main() {
    scanf("%d%d",&n,&m);
    int flip = 0;
    if (min(n,m)==1 && m==1) flip = 1, swap(n,m);
    for (int i=0;i<n;i++) for (int j=0;j<m;j++) scanf("%d",&A[i][j]);
    for (int i=0;i<n;i++) for (int j=0;j<m;j++) scanf("%d",&B[i][j]);
    for (int i=0;i<n;i++) for (int j=0;j<m;j++) {
        Ball next;
        next.color = A[i][j]; next.x = i; next.y = j; next.goX = -1;
        balls[i][j] = next;
        cur[i][j] = &balls[i][j];
    }
    if (min(n,m)==1) solve1();
    else solve();
    if (flip) swap(n,m);
    if (print.size()) {
        printf("%d\n",print.size()-1);
        for (int i=0;i<print.size();i++) printf("%d %d\n",print[i]/m+1,print[i]%m+1);
    } else printf("-1\n");
}


#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

struct Ball { int color,x,y,goX,goY;};

int n,m;
Ball balls[30][30];
Ball* c;
int A[30][30];
int tmp[30][30];
int B[30][30];
Ball* cur[30][30];
Ball* need[30][30];
vector<int> print;

void go(int dx, int dy) {
    int x = c->x, y = c->y;
    int nx = x+dx, ny = y+dy;
    print.push_back(nx*m+ny);
    Ball* next = cur[nx][ny];
    swap(cur[x][y],cur[nx][ny]);
    c->x = nx, c->y = ny;
    next->x = x, next->y = y;
}

void solve1() {
    int ok = 0;
    for (int a=0;a<m && !ok;a++) {
        for (int b=0;b<m && !ok;b++) {
            print.clear();
            for (int i=0;i<m;i++) tmp[0][i] = A[0][i];
            int cur = a;
            print.push_back(cur);
            while (cur<b) swap(tmp[0][cur],tmp[0][cur+1]), cur+=1, print.push_back(cur);
            while (cur>b) swap(tmp[0][cur],tmp[0][cur-1]), cur-=1, print.push_back(cur);
            int good = 1;
            for (int i=0;i<m;i++) if (tmp[0][i]!=B[0][i]) good = 0;
            if (good) ok = 1;
        }
    }
    if (!ok) print.clear();
}

void getvert(Ball* which, int off) {
    if (c->x!=n-1) go(1,0);
    if (c->x==which->x) go(which->x==n-1 ? -1 : 1,0);
    while (c->y<which->y) go(0,1);
    while (c->y>which->y) go(0,-1);
    while (c->x<which->x+off) go(1,0);
    while (c->x>which->x+off) go(-1,0);
}

void solve() {
    for (int i=0;i<n;i++) for (int j=0;j<m;j++) {
        int found = 0;
        for (int a=0;a<n && !found;a++) for (int b=0;b<m && !found;b++) {
            if (cur[a][b]->goX==-1 && cur[a][b]->color==B[i][j]) {
                found = 1;
                cur[a][b]->goX = i; cur[a][b]->goY = j;
                need[i][j] = cur[a][b];
            }
        }
        if (found==0) return;
    }
    c = need[n-1][m-1];
    print.push_back(c->x*m+c->y);
    for (int i=0;i<n-2;i++) for (int j=0;j<m;j++) {
        if (need[i][j]->x==n-1) getvert(need[i][j],-1), go(1,0);
        else getvert(need[i][j],+1);
        while (c->y!=j) {
            int l = c->y>j;
            go(-1,l ? -1 : 1);
            go(0,l ? 1 : -1);
            go(1,l ? -1 : 1);
        }
        while (c->x>i+1) {
            int l = j>0;
            go(-1,l ? -1 : 1);
            go(-1,l ? 1 : -1);
            go(1,0);
        }
    }
    while (c->y>0) go(0,-1);
    if (c->x!=n-1) go(1,0);
    for (int j=0;j<m-2;j++) for (int i=n-2;i<n;i++) {
        if (need[i][j]->x==i && need[i][j]->y==j) {
            if (i==n-2) go(-1,1);
            else go(1,0);
            continue;
        }
        if (c->x==need[i][j]->x) go(c->x==n-1 ? -1 : 1,0);
        while (c->y<need[i][j]->y) go(0,1);
        if (need[i][j]->x!=i) go(c->x==n-1 ? -1 : 1,0);
        go(c->x==n-1 ? -1 : 1,-1);
        go(0,1);
        while (need[i][j]->y>j) {
            int d = c->x==n-1;
            go(d ? -1 : 1,-1);
            go(d ? 1 : -1,-1);
            go(0,1);
        }
    }
    if (need[n-2][m-2]->x!=n-2 || need[n-2][m-2]->y!=m-2) {
        go(-1,0);
        go(need[n-2][m-2]->x-c->x,need[n-2][m-2]->y-c->y);
        if (c->y==m-1) go(c->x==n-1 ? 0 : 1,-1);
    }
    if (need[n-1][m-2]->x!=n-1 || need[n-1][m-2]->y!=m-2) go(need[n-1][m-2]->x-c->x,need[n-1][m-2]->y-c->y);
    if (c->x!=n-1) go(1,0);
}

int main() {
    scanf("%d%d",&n,&m);
    int flip = 0;
    if (min(n,m)==1 && m==1) flip = 1, swap(n,m);
    for (int i=0;i<n;i++) for (int j=0;j<m;j++) scanf("%d",&A[i][j]);
    for (int i=0;i<n;i++) for (int j=0;j<m;j++) scanf("%d",&B[i][j]);
    for (int i=0;i<n;i++) for (int j=0;j<m;j++) {
        Ball next;
        next.color = A[i][j]; next.x = i; next.y = j; next.goX = -1;
        balls[i][j] = next;
        cur[i][j] = &balls[i][j];
    }
    if (min(n,m)==1) solve1();
    else solve();
    if (flip) swap(n,m);
    if (print.size()) {
        printf("%d\n",print.size()-1);
        for (int i=0;i<print.size();i++) printf("%d %d\n",print[i]/m+1,print[i]%m+1);
    } else printf("-1\n");
}


#include<bits/stdc++.h>
using namespace std;
const double eps(1e-8);
const double pi(3.14159265358979);
const int x_[8]={0,1,1,1,0,-1,-1,-1};
const int y_[8]={1,1,0,-1,-1,-1,0,1};
const int N=33,M=33,K=1000010,D=(N+M)*10,C=909;
int n,m,s[N][M]={},to[N][M]={},x[K]={},y[K]={},tot=-1;
bool reverse_xy=false,ok[N][M]={};
inline int abs(int x)
{
	return x>=0 ? x : -x;
}
inline void add_next(int x_,int y_) //Suppose that tot>=0 before.
{
	swap(s[x_][y_],s[x[tot]][y[tot]]);
	++tot,x[tot]=x_,y[tot]=y_;
}
void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&s[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&to[i][j]);
}
bool same()
{
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(s[i][j]!=to[i][j])
				return false;
	return true;
}
bool impossible()
{
	int t[C]={};
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			++t[s[i][j]],--t[to[i][j]];
	for(int i=1;i<=900;++i)
		if(t[i])
			return true;
	return false;
}
bool adjust(int x1,int y1)
{
	int x2=0,y2=0,x3=x[tot],y3=y[tot];
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(!ok[i][j] && s[i][j]==to[x1][y1] && (i!=x3 || j!=y3))
				x2=i,y2=j;
	int mind=abs(x3-x2)+abs(y3-y2);
	while(mind>1)
	{
		int dir=rand()%8,nx3=x3+x_[dir],ny3=y3+y_[dir];
		int nowd=abs(nx3-x2)+abs(ny3-y2);
		if(ok[nx3][ny3] || nowd>=mind || (nx3==x2 && ny3==y2))
			continue;
		mind=nowd;
		x3=nx3,y3=ny3;
		add_next(x3,y3);
	}
	mind=(abs(x2-x1)+abs(y2-y1))/*D+abs(x3-x1)+abs(y3-y1)*/;
	while(x2!=x1 || y2!=y1)
	{
		int dir=rand()%8,nx3=x3+x_[dir],ny3=y3+y_[dir],nx2=x2,ny2=y2;
		if(nx3==x2 && ny3==y2)
			nx2=x3,ny2=y3;
		if(ok[nx3][ny3] || abs(nx3-nx2)>1 || abs(ny3-ny2)>1)
			continue;
		int nowd=(abs(nx2-x1)+abs(ny2-y1))/*D+abs(nx3-x1)+abs(ny3-y1)*/;
		if(nowd<=mind)
		{
			add_next(nx3,ny3);
			x2=nx2,y2=ny2,x3=nx3,y3=ny3;
			mind=nowd;
		}
	}
	ok[x1][y1]=true;
	return true;
}
void work()
{
	if(impossible())
		return;
	if(n>m)
	{
		for(int i=1;i<=n;++i)
			for(int j=i;j<=n;++j)
				swap(s[i][j],s[j][i]),swap(to[i][j],to[j][i]);
		reverse_xy=true;
		swap(n,m);
	}
	if(same())
	{
		++tot,x[0]=1,y[0]=1;
		return;
	}
	for(int i=0;i<=m+1;++i)
		ok[0][i]=ok[n+1][i]=true;
	for(int i=0;i<=n+1;++i)
		ok[i][0]=ok[i][m+1]=true;
	if(n==1)
	{
		int l=1,r=m;
		while(l<=m && s[1][l]==to[1][l])
			++l;
		while(r>=0 && s[1][r]==to[1][r])
			--r; // has guaranteed that s[] and to[] are different.
		bool flag=s[1][r]==to[1][l];
		for(int i=l;i<r && flag;++i)
			flag&=(s[1][i]==to[1][i+1]);
		if(flag)
			for(int i=r;i>=l;--i)
				++tot,x[tot]=1,y[tot]=i;
		flag=!flag && s[1][l]==to[1][r];
		for(int i=l;i<r && flag;++i)
			flag&=to[1][i]==s[1][i+1];
		if(flag)
			for(int i=l;i<=r;++i)
				++tot,x[tot]=1,y[tot]=i;
	}
	else
	{
		for(int i=1;i<=n && tot==-1;++i)
			for(int j=1;j<=m && tot==-1;++j)
				if(s[i][j]==to[n][m])
					++tot,x[tot]=i,y[tot]=j;
		bool flag=true;
		for(int i=1;i<=n-2 && flag;++i)
			for(int j=1;j<=m && flag;++j)
				flag&=adjust(i,j);
		for(int j=1;j<m && flag;++j)
			flag&=adjust(n-1,j) && adjust(n,j);
		if(flag)
			flag&=adjust(n-1,m);
		if(!flag)
			tot=-1;
	}
}
void print()
{
	printf("%d\n",tot);
	for(int i=0;i<=tot;++i)
		if(reverse_xy)
			printf("%d %d\n",y[i],x[i]);
		else
			printf("%d %d\n",x[i],y[i]);
}
int main()
{
	srand(time(0));
	init();
	work();
	print();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<fstream>
#include<functional>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<stdexcept>
#include<string>
#include<vector>
#include<utility>
using namespace std;
const double eps(1e-8);
const double pi(3.14159265358979);
const int x_[8]={0,1,1,1,0,-1,-1,-1};
const int y_[8]={1,1,0,-1,-1,-1,0,1};
const int N=35,M=35,K=1000010;
int n,m,s[N][M]={},to[N][M]={},x[K]={},y[K]={},tot=-1;
bool flag=false,ok[N][M]={};
void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&s[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&to[i][j]);
}
void print_graph()
{
	cout<<"------------------"<<endl;
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
			cout<<s[i][j]<<' ';
		cout<<endl;
	}
	cout<<"tot="<<tot<<endl;
	for(int i=0;i<=tot;++i)
		cout<<x[i]<<' '<<y[i]<<endl;
	cout<<"------------------"<<endl;
}
bool check()
{
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(s[i][j]!=to[i][j])
				return false;
	return true;
}
void move_around(int sx,int sy,int ex,int ey)
{
	int px[N*M]={},py[N*M]={},f[N*M]={},head=0,tail=0;
	bool in[N][M]={};
	++tail;
	in[sx][sy]=true;
	px[tail]=sx;
	py[tail]=sy;
	while(head!=tail)
	{
		++head;
		int x1=px[head],y1=py[head];
		for(int i=0;i<8;++i)
		{
			int tx=x1+x_[i],ty=y1+y_[i];
			if(ok[tx][ty] || in[tx][ty])
				continue;
			++tail;
			in[tx][ty]=true;
			px[tail]=tx;
			py[tail]=ty;
			f[tail]=head;
			if(tx==ex && ty==ey)
			{
				int pos=f[tail],stx[N*M]={},sty[N*M]={},top=0;
				while(f[pos])
				{
					++top;
					stx[top]=px[pos];
					sty[top]=py[pos];
					pos=f[pos];
				}
				for(int t=top;t>=1;--t)
				{
					++tot;
					x[tot]=stx[t];
					y[tot]=sty[t];
					swap(s[x[tot-1]][y[tot-1]],s[x[tot]][y[tot]]);
				}
				return;
			}
		}
	}
}
inline int abs(int x)
{
	return x>=0 ? x : -x;
}
void move_to(int space_x,int space_y,int sx,int sy,int ex,int ey)
{
	//cout<<"space_x="<<space_x<<" space_y="<<space_y;
	//cout<<"sx="<<sx<<" sy="<<sy<<" ex="<<ex<<" ey="<<ey<<endl;
	const int S=N*M*8;
	int nx[S]={},ny[S]={},rx[S]={},ry[S]={},f[S]={},head=0,tail=0;
	static bool in[N][M][N][M]={};
	++tail;
	in[sx][sy][space_x][space_y]=true;
	rx[tail]=space_x,ry[tail]=space_y,nx[tail]=sx,ny[tail]=sy;
	while(head!=tail)
	{
		++head;
		int nowx=nx[head],nowy=ny[head],spacex=rx[head],spacey=ry[head];
		for(int i=0;i<8;++i)
		{
			int nspacex=spacex+x_[i],nspacey=spacey+y_[i];
			int nnowx=nowx,nnowy=nowy;
			if(nspacex==nowx && nspacey==nowy)
				nnowx=spacex,nnowy=spacey;
			if(ok[nnowx][nnowy] || ok[nspacex][nspacey]
			|| in[nnowx][nnowy][nspacex][nspacey])
				continue;
			if(max(abs(nnowx-nspacex),abs(nnowy-nspacey))>1)
				continue;
			++tail;
			in[nnowx][nnowy][nspacex][nspacey]=true;
			rx[tail]=nspacex,ry[tail]=nspacey;
			nx[tail]=nnowx,ny[tail]=nnowy;
			f[tail]=head;
			if(nx[tail]==ex && ny[tail]==ey)
			{
				int pos=tail,stx[N*M]={},sty[N*M]={},top=0;
				while(f[pos])
				{
					++top;
					stx[top]=rx[pos];
					sty[top]=ry[pos];
					pos=f[pos];
				}
				//cout<<"top="<<top<<endl;
				for(int t=top;t>=1;--t)
				{
					//print_graph();
					++tot;
					x[tot]=stx[t];
					y[tot]=sty[t];
					swap(s[x[tot-1]][y[tot-1]],s[x[tot]][y[tot]]);
					//print_graph();
				}
				for(int t=1;t<=tail;++t)
					in[nx[t]][ny[t]][rx[t]][ry[t]]=false;
				return;
			}
		}
	}
}
bool adjust(int xto,int yto)
{
	//cout<<"xto="<<xto<<" yto="<<yto<<endl;
	int x1=0,y1=0;
	for(int i=1;i<=n && !x1;++i)
		for(int j=1;j<=m && !y1;++j)
			if(!ok[i][j] && (i!=x[tot] || j!=y[tot]) && s[i][j]==to[xto][yto])
				x1=i,y1=j;
	//cout<<"x1="<<x1<<" y1="<<y1<<endl;
	if(!x1 && !y1)
	{
		tot=-1;
		return false;
	}
	//cout<<"x[tot]="<<x[tot]<<" y[tot]="<<y[tot]<<endl;
	move_around(x[tot],y[tot],x1,y1);
	//cout<<"tot="<<tot<<endl;
	//cout<<"x[tot]="<<x[tot]<<" y[tot]="<<y[tot]<<endl;
	move_to(x[tot],y[tot],x1,y1,xto,yto);
	return true;
}
void work()
{
	if(n>m)
	{
		for(int i=1;i<=n;++i)
			for(int j=i;j<=n;++j)
				swap(s[i][j],s[j][i]),swap(to[i][j],to[j][i]);
		flag=true;
		swap(n,m);
	}
	for(int i=0;i<=m+1;++i)
		ok[0][i]=ok[n+1][i]=true;
	for(int i=0;i<=n+1;++i)
		ok[i][0]=ok[i][m+1]=true;
	if(n==1)
	{
		int c[M]={};
		for(int i=1;i<=m;++i)
		{
			copy(s[1]+1,s[1]+m+1,c+1);
			for(int j=i+1;j<=m;++j)
			{
				swap(s[1][j],s[1][j-1]);
				if(check())
				{
					for(int k=i;k<=j;++k)
						++tot,x[tot]=1,y[tot]=k;
					return;
				}
			}
			copy(c+1,c+m+1,s[1]+1);
			for(int j=i-1;j>=1;--j)
			{
				swap(s[1][j],s[1][j+1]);
				if(check())
				{
					for(int k=i;k>=j;--k)
						++tot,x[tot]=1,y[tot]=k;
					return;
				}
			}
			copy(c+1,c+m+1,s[1]+1);
		}
	}
	else
	{
		++tot;
		int toc=to[n][m];
		for(int i=1;i<=n && !x[tot];++i)
			for(int j=1;j<=m && !y[tot];++j)
				if(s[i][j]==toc)
				{
					x[tot]=i;
					y[tot]=j;
				}
		for(int i=1;i<=n-2;++i)
			for(int j=1;j<=m;++j)
			{
				if(s[i][j]!=to[i][j])
				{
					if(!adjust(i,j))
						return;
				}
				ok[i][j]=true;
			}
		for(int j=1;j<=m;++j)
		{
			if(s[n-1][j]!=to[n-1][j])
			{
				if(!adjust(n-1,j))
					return;
			}
			print_graph();
			ok[n-1][j]=true;
			if(s[n][j]!=to[n][j])
			{
				if(!adjust(n,j))
					return;
			}
			ok[n][j]=true;
			print_graph();
		}
	}
}
void print()
{
	printf("%d\n",tot);
	for(int i=0;i<=tot;++i)
		if(flag)
			printf("%d %d\n",y[i],x[i]);
		else
			printf("%d %d\n",x[i],y[i]);
}
int main()
{
	init();
	work();
	print();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<fstream>
#include<functional>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<stdexcept>
#include<string>
#include<vector>
#include<utility>
using namespace std;
const double eps(1e-8);
const double pi(3.14159265358979);
const int x_[8]={0,1,1,1,0,-1,-1,-1};
const int y_[8]={1,1,0,-1,-1,-1,0,1};
const int N=35,M=35,K=1000010;
int n,m,s[N][M]={},to[N][M]={},x[K]={},y[K]={},tot=-1;
bool flag=false,ok[N][M]={};
void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&s[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&to[i][j]);
}
void Print_graph()
{
	cout<<"------------------"<<endl;
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
			cout<<s[i][j]<<' ';
		cout<<endl;
	}
	cout<<"tot="<<tot<<endl;
	for(int i=0;i<=tot;++i)
		cout<<x[i]<<' '<<y[i]<<endl;
	cout<<"------------------"<<endl;
}
bool check()
{
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(s[i][j]!=to[i][j])
				return false;
	return true;
}
void move_around(int sx,int sy,int ex,int ey)
{
	int px[N*M]={},py[N*M]={},f[N*M]={},head=0,tail=0;
	bool in[N][M]={};
	++tail;
	in[sx][sy]=true;
	px[tail]=sx;
	py[tail]=sy;
	while(head!=tail)
	{
		++head;
		int x1=px[head],y1=py[head];
		for(int i=0;i<8;++i)
		{
			int tx=x1+x_[i],ty=y1+y_[i];
			if(ok[tx][ty] || in[tx][ty])
				continue;
			++tail;
			in[tx][ty]=true;
			px[tail]=tx;
			py[tail]=ty;
			f[tail]=head;
			if(tx==ex && ty==ey)
			{
				int pos=f[tail],stx[N*M]={},sty[N*M]={},top=0;
				while(f[pos])
				{
					++top;
					stx[top]=px[pos];
					sty[top]=py[pos];
					pos=f[pos];
				}
				for(int t=top;t>=1;--t)
				{
					++tot;
					x[tot]=stx[t];
					y[tot]=sty[t];
					swap(s[x[tot-1]][y[tot-1]],s[x[tot]][y[tot]]);
				}
				return;
			}
		}
	}
}
inline int abs(int x)
{
	return x>=0 ? x : -x;
}
void move_to(int space_x,int space_y,int sx,int sy,int ex,int ey)
{
	//cout<<"space_x="<<space_x<<" space_y="<<space_y;
	//cout<<"sx="<<sx<<" sy="<<sy<<" ex="<<ex<<" ey="<<ey<<endl;
	const int S=N*M*8;
	int nx[S]={},ny[S]={},rx[S]={},ry[S]={},f[S]={},head=0,tail=0;
	static bool in[N][M][N][M]={};
	++tail;
	in[sx][sy][space_x][space_y]=true;
	rx[tail]=space_x,ry[tail]=space_y,nx[tail]=sx,ny[tail]=sy;
	while(head!=tail)
	{
		++head;
		int nowx=nx[head],nowy=ny[head],spacex=rx[head],spacey=ry[head];
		for(int i=0;i<8;++i)
		{
			int nspacex=spacex+x_[i],nspacey=spacey+y_[i];
			int nnowx=nowx,nnowy=nowy;
			if(nspacex==nowx && nspacey==nowy)
				nnowx=spacex,nnowy=spacey;
			if(ok[nnowx][nnowy] || ok[nspacex][nspacey]
			|| in[nnowx][nnowy][nspacex][nspacey])
				continue;
			if(max(abs(nnowx-nspacex),abs(nnowy-nspacey))>1)
				continue;
			++tail;
			in[nnowx][nnowy][nspacex][nspacey]=true;
			rx[tail]=nspacex,ry[tail]=nspacey;
			nx[tail]=nnowx,ny[tail]=nnowy;
			f[tail]=head;
			if(nx[tail]==ex && ny[tail]==ey)
			{
				int pos=f[tail],stx[N*M]={},sty[N*M]={},top=0;
				while(pos)
				{
					++top;
					stx[top]=nx[pos];
					sty[top]=ny[pos];
					pos=f[pos];
				}
				//cout<<"top="<<top<<endl;
				for(int t=top;t>=1;--t)
				{
					//print_graph();
					++tot;
					x[tot]=stx[t];
					y[tot]=sty[t];
					swap(s[x[tot-1]][y[tot-1]],s[x[tot]][y[tot]]);
					//print_graph();
				}
				for(int t=1;t<=tail;++t)
					in[nx[t]][ny[t]][rx[t]][ry[t]]=false;
				return;
			}
		}
	}
}
bool adjust(int xto,int yto)
{
	//cout<<"xto="<<xto<<" yto="<<yto<<endl;
	int x1=0,y1=0;
	for(int i=1;i<=n && !x1;++i)
		for(int j=1;j<=m && !y1;++j)
			if(!ok[i][j] && (i!=x[tot] || j!=y[tot]) && s[i][j]==to[xto][yto])
				x1=i,y1=j;
	//cout<<"x1="<<x1<<" y1="<<y1<<endl;
	if(!x1 && !y1)
	{
		tot=-1;
		return false;
	}
	//cout<<"x[tot]="<<x[tot]<<" y[tot]="<<y[tot]<<endl;
	move_around(x[tot],y[tot],x1,y1);
	//cout<<"tot="<<tot<<endl;
	//cout<<"x[tot]="<<x[tot]<<" y[tot]="<<y[tot]<<endl;
	move_to(x[tot],y[tot],x1,y1,xto,yto);
	return true;
}
void work()
{
	if(n>m)
	{
		for(int i=1;i<=n;++i)
			for(int j=i;j<=n;++j)
				swap(s[i][j],s[j][i]),swap(to[i][j],to[j][i]);
		flag=true;
		swap(n,m);
	}
	for(int i=0;i<=m+1;++i)
		ok[0][i]=ok[n+1][i]=true;
	for(int i=0;i<=n+1;++i)
		ok[i][0]=ok[i][m+1]=true;
	if(n==1)
	{
		int c[M]={};
		for(int i=1;i<=m;++i)
		{
			copy(s[1]+1,s[1]+m+1,c+1);
			for(int j=i+1;j<=m;++j)
			{
				swap(s[1][j],s[1][j-1]);
				if(check())
				{
					for(int k=i;k<=j;++k)
						++tot,x[tot]=1,y[tot]=k;
					return;
				}
			}
			copy(c+1,c+m+1,s[1]+1);
			for(int j=i-1;j>=1;--j)
			{
				swap(s[1][j],s[1][j+1]);
				if(check())
				{
					for(int k=i;k>=j;--k)
						++tot,x[tot]=1,y[tot]=k;
					return;
				}
			}
			copy(c+1,c+m+1,s[1]+1);
		}
	}
	else
	{
		++tot;
		int toc=to[n][m];
		for(int i=1;i<=n && !x[tot];++i)
			for(int j=1;j<=m && !y[tot];++j)
				if(s[i][j]==toc)
				{
					x[tot]=i;
					y[tot]=j;
				}
		for(int i=1;i<=n-2;++i)
			for(int j=1;j<=m;++j)
			{
				if(s[i][j]!=to[i][j])
				{
					if(!adjust(i,j))
						return;
				}
				ok[i][j]=true;
			}
		for(int j=1;j<=m;++j)
		{
			if(s[n-1][j]!=to[n-1][j])
			{
				if(!adjust(n-1,j))
					return;
			}
			//print_graph();
			ok[n-1][j]=true;
			if(s[n][j]!=to[n][j])
			{
				if(!adjust(n,j))
					return;
			}
			ok[n][j]=true;
			//print_graph();
		}
	}
}
void print()
{
	printf("%d\n",tot);
	for(int i=0;i<=tot;++i)
		if(flag)
			printf("%d %d\n",y[i],x[i]);
		else
			printf("%d %d\n",x[i],y[i]);
}
int main()
{
	init();
	work();
	print();
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const double eps(1e-8);
const double pi(3.14159265358979);
const int x_[8]={0,1,1,1,0,-1,-1,-1};
const int y_[8]={1,1,0,-1,-1,-1,0,1};
const int N=33,M=33,K=1000010,D=(N+M)*10,C=909;
int n,m,s[N][M]={},to[N][M]={},x[K]={},y[K]={},tot=-1;
bool reverse_xy=false,ok[N][M]={};
inline int abs(int x)
{
	return x>=0 ? x : -x;
}
inline void prints()
{
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
			cout<<s[i][j]<<' ';
		cout<<endl;
	}
	cout<<"--------------------"<<endl;
}
inline void printto()
{
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
			cout<<to[i][j]<<' ';
		cout<<endl;
	}
	cout<<"--------------------"<<endl;
}
inline void add_next(int x_,int y_) //Suppose that tot>=0 before.
{
	swap(s[x_][y_],s[x[tot]][y[tot]]);
	++tot,x[tot]=x_,y[tot]=y_;
}
void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&s[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&to[i][j]);
}
bool same()
{
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(s[i][j]!=to[i][j])
				return false;
	return true;
}
bool impossible()
{
	int t[C]={};
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			++t[s[i][j]],--t[to[i][j]];
	for(int i=1;i<=900;++i)
		if(t[i])
			return true;
	return false;
}
bool adjust(int x1,int y1)
{
	int x2=0,y2=0,x3=x[tot],y3=y[tot];
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(!ok[i][j] && s[i][j]==to[x1][y1] && (i!=x3 || j!=y3))
				x2=i,y2=j;
	int mind=abs(x3-x2)+abs(y3-y2);
	//cout<<"x1="<<x1<<" y1="<<y1<<" x2="<<x2<<" y2="<<y2;
	//cout<<" x3="<<x3<<" y3="<<y3<<endl;
	//prints();
	//printto();
	while(mind>1)
	{
		int dir=rand()%8,nx3=x3+x_[dir],ny3=y3+y_[dir];
		//cout<<"nx3="<<nx3<<" ny3="<<ny3<<endl;
		int nowd=abs(nx3-x2)+abs(ny3-y2);
		//cout<<"x2="<<x2<<" y2="<<y2<<endl;
		if(ok[nx3][ny3] || nowd>=mind || (nx3==x2 && ny3==y2))
			continue;
		mind=nowd;
		x3=nx3,y3=ny3;
		add_next(x3,y3);
	}
	//prints();
	mind=(abs(x2-x1)+abs(y2-y1))*D+abs(x3-x1)+abs(y3-y1);
	while(x2!=x1 || y2!=y1)
	{
		int dir=rand()%8,nx3=x3+x_[dir],ny3=y3+y_[dir],nx2=x2,ny2=y2;
		if(nx3==x2 && ny3==y2)
			nx2=x3,ny2=y3;
		if(ok[nx3][ny3] || abs(nx3-nx2)>1 || abs(ny3-ny2)>1)
			continue;
		int nowd=(abs(nx2-x1)+abs(ny2-y1))*D+abs(nx3-x1)+abs(ny3-y1);
		if(nowd<=mind)
		{
			add_next(nx3,ny3);
			x2=nx2,y2=ny2,x3=nx3,y3=ny3;
			mind=nowd;
		}
	}
	ok[x1][y1]=true;
	//prints();
	//cout<<endl;
	return true;
}
void work()
{
	if(impossible())
		return;
	if(n>m)
	{
		for(int i=1;i<=n;++i)
			for(int j=i;j<=n;++j)
				swap(s[i][j],s[j][i]),swap(to[i][j],to[j][i]);
		reverse_xy=true;
		swap(n,m);
	}
	if(same())
	{
		++tot,x[0]=1,y[0]=1;
		return;
	}
	for(int i=0;i<=m+1;++i)
		ok[0][i]=ok[n+1][i]=true;
	for(int i=0;i<=n+1;++i)
		ok[i][0]=ok[i][m+1]=true;
	if(n==1)
	{
		int l=1,r=m;
		while(l<=m && s[1][l]==to[1][l])
			++l;
		while(r>=0 && s[1][r]==to[1][r])
			--r; // has guaranteed that s[] and to[] are different.
		bool flag=s[1][r]==to[1][l];
		for(int i=l;i<r && flag;++i)
			flag&=(s[1][i]==to[1][i+1]);
		if(flag)
			for(int i=r;i>=l;--i)
				++tot,x[tot]=1,y[tot]=i;
		flag=!flag && s[1][l]==to[1][r];
		for(int i=l;i<r && flag;++i)
			flag&=to[1][i]==s[1][i+1];
		if(flag)
			for(int i=l;i<=r;++i)
				++tot,x[tot]=1,y[tot]=i;
	}
	else
	{
		for(int i=1;i<=n && tot==-1;++i)
			for(int j=1;j<=m && tot==-1;++j)
				if(s[i][j]==to[n][m])
					++tot,x[tot]=i,y[tot]=j;
		bool flag=true;
		for(int i=1;i<=n-2 && flag;++i)
			for(int j=1;j<=m && flag;++j)
				flag&=adjust(i,j);
		for(int j=1;j<m && flag;++j)
			flag&=adjust(n-1,j) && adjust(n,j);
		if(flag)
			flag&=adjust(n-1,m);
		if(!flag)
			tot=-1;
	}
}
void print()
{
	printf("%d\n",tot);
	for(int i=0;i<=tot;++i)
		if(reverse_xy)
			printf("%d %d\n",y[i],x[i]);
		else
			printf("%d %d\n",x[i],y[i]);
}
int main()
{
	srand(time(0));
	init();
	work();
	print();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<fstream>
#include<functional>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<stdexcept>
#include<string>
#include<vector>
#include<utility>
using namespace std;
const double eps(1e-8);
const double pi(3.14159265358979);
const int x_[8]={0,1,1,1,0,-1,-1,-1};
const int y_[8]={1,1,0,-1,-1,-1,0,1};
const int N=35,M=35,K=1000010;
int n,m,s[N][M]={},to[N][M]={},x[K]={},y[K]={},tot=-1;
bool flag=false,ok[N][M]={};
void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&s[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&to[i][j]);
}
void print_graph()
{
	cout<<"------------------"<<endl;
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
			cout<<s[i][j]<<' ';
		cout<<endl;
	}
	cout<<"tot="<<tot<<endl;
	for(int i=0;i<=tot;++i)
		cout<<x[i]<<' '<<y[i]<<endl;
	cout<<"------------------"<<endl;
}
bool check()
{
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(s[i][j]!=to[i][j])
				return false;
	return true;
}
void move_around(int sx,int sy,int ex,int ey)
{
	int px[N*M]={},py[N*M]={},f[N*M]={},head=0,tail=0;
	bool in[N][M]={};
	++tail;
	in[sx][sy]=true;
	px[tail]=sx;
	py[tail]=sy;
	while(head!=tail)
	{
		++head;
		int x1=px[head],y1=py[head];
		for(int i=0;i<8;++i)
		{
			int tx=x1+x_[i],ty=y1+y_[i];
			if(ok[tx][ty] || in[tx][ty])
				continue;
			++tail;
			in[tx][ty]=true;
			px[tail]=tx;
			py[tail]=ty;
			f[tail]=head;
			if(tx==ex && ty==ey)
			{
				int pos=f[tail],stx[N*M]={},sty[N*M]={},top=0;
				while(f[pos])
				{
					++top;
					stx[top]=px[pos];
					sty[top]=py[pos];
					pos=f[pos];
				}
				for(int t=top;t>=1;--t)
				{
					++tot;
					x[tot]=stx[t];
					y[tot]=sty[t];
					swap(s[x[tot-1]][y[tot-1]],s[x[tot]][y[tot]]);
				}
				return;
			}
		}
	}
}
inline int abs(int x)
{
	return x>=0 ? x : -x;
}
void move_to(int space_x,int space_y,int sx,int sy,int ex,int ey)
{
	//cout<<"space_x="<<space_x<<" space_y="<<space_y;
	//cout<<"sx="<<sx<<" sy="<<sy<<" ex="<<ex<<" ey="<<ey<<endl;
	const int S=N*M*8;
	int nx[S]={},ny[S]={},rx[S]={},ry[S]={},f[S]={},head=0,tail=0;
	static bool in[N][M][N][M]={};
	++tail;
	in[sx][sy][space_x][space_y]=true;
	rx[tail]=space_x,ry[tail]=space_y,nx[tail]=sx,ny[tail]=sy;
	while(head!=tail)
	{
		++head;
		int nowx=nx[head],nowy=ny[head],spacex=rx[head],spacey=ry[head];
		for(int i=0;i<8;++i)
		{
			int nspacex=spacex+x_[i],nspacey=spacey+y_[i];
			int nnowx=nowx,nnowy=nowy;
			if(nspacex==nowx && nspacey==nowy)
				nnowx=spacex,nnowy=spacey;
			if(ok[nnowx][nnowy] || ok[nspacex][nspacey]
			|| in[nnowx][nnowy][nspacex][nspacey])
				continue;
			if(max(abs(nnowx-nspacex),abs(nnowy-nspacey))>1)
				continue;
			++tail;
			in[nnowx][nnowy][nspacex][nspacey]=true;
			rx[tail]=nspacex,ry[tail]=nspacey;
			nx[tail]=nnowx,ny[tail]=nnowy;
			f[tail]=head;
			if(nx[tail]==ex && ny[tail]==ey)
			{
				int pos=tail,stx[N*M]={},sty[N*M]={},top=0;
				while(f[pos])
				{
					++top;
					stx[top]=rx[pos];
					sty[top]=ry[pos];
					pos=f[pos];
				}
				//cout<<"top="<<top<<endl;
				for(int t=top;t>=1;--t)
				{
					//print_graph();
					++tot;
					x[tot]=stx[t];
					y[tot]=sty[t];
					swap(s[x[tot-1]][y[tot-1]],s[x[tot]][y[tot]]);
					//print_graph();
				}
				for(int t=1;t<=tail;++t)
					in[nx[t]][ny[t]][rx[t]][ry[t]]=false;
				return;
			}
		}
	}
}
bool adjust(int xto,int yto)
{
	//cout<<"xto="<<xto<<" yto="<<yto<<endl;
	int x1=0,y1=0;
	for(int i=1;i<=n && !x1;++i)
		for(int j=1;j<=m && !y1;++j)
			if(!ok[i][j] && (i!=x[tot] || j!=y[tot]) && s[i][j]==to[xto][yto])
				x1=i,y1=j;
	//cout<<"x1="<<x1<<" y1="<<y1<<endl;
	if(!x1 && !y1)
	{
		tot=-1;
		return false;
	}
	//cout<<"x[tot]="<<x[tot]<<" y[tot]="<<y[tot]<<endl;
	move_around(x[tot],y[tot],x1,y1);
	//cout<<"tot="<<tot<<endl;
	//cout<<"x[tot]="<<x[tot]<<" y[tot]="<<y[tot]<<endl;
	move_to(x[tot],y[tot],x1,y1,xto,yto);
	return true;
}
void work()
{
	if(n>m)
	{
		for(int i=1;i<=n;++i)
			for(int j=i;j<=n;++j)
				swap(s[i][j],s[j][i]),swap(to[i][j],to[j][i]);
		flag=true;
		swap(n,m);
	}
	for(int i=0;i<=m+1;++i)
		ok[0][i]=ok[n+1][i]=true;
	for(int i=0;i<=n+1;++i)
		ok[i][0]=ok[i][m+1]=true;
	if(n==1)
	{
		int c[M]={};
		for(int i=1;i<=m;++i)
		{
			copy(s[1]+1,s[1]+m+1,c+1);
			for(int j=i+1;j<=m;++j)
			{
				swap(s[1][j],s[1][j-1]);
				if(check())
				{
					for(int k=i;k<=j;++k)
						++tot,x[tot]=1,y[tot]=k;
					return;
				}
			}
			copy(c+1,c+m+1,s[1]+1);
			for(int j=i-1;j>=1;--j)
			{
				swap(s[1][j],s[1][j+1]);
				if(check())
				{
					for(int k=i;k>=j;--k)
						++tot,x[tot]=1,y[tot]=k;
					return;
				}
			}
			copy(c+1,c+m+1,s[1]+1);
		}
	}
	else
	{
		++tot;
		int toc=to[n][m];
		for(int i=1;i<=n && !x[tot];++i)
			for(int j=1;j<=m && !y[tot];++j)
				if(s[i][j]==toc)
				{
					x[tot]=i;
					y[tot]=j;
				}
		for(int i=1;i<=n-2;++i)
			for(int j=1;j<=m;++j)
			{
				if(s[i][j]!=to[i][j])
				{
					if(!adjust(i,j))
						return;
				}
				ok[i][j]=true;
			}
		for(int j=1;j<=m;++j)
		{
			if(s[n-1][j]!=to[n-1][j])
			{
				if(!adjust(n-1,j))
					return;
			}
			//print_graph();
			ok[n-1][j]=true;
			if(s[n][j]!=to[n][j])
			{
				if(!adjust(n,j))
					return;
			}
			ok[n][j]=true;
			//print_graph();
		}
	}
}
void print()
{
	printf("%d\n",tot);
	for(int i=0;i<=tot;++i)
		if(flag)
			printf("%d %d\n",y[i],x[i]);
		else
			printf("%d %d\n",x[i],y[i]);
}
int main()
{
	init();
	work();
	print();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<deque>
#include<fstream>
#include<functional>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<stdexcept>
#include<string>
#include<vector>
#include<utility>
using namespace std;
const double eps(1e-8);
const double pi(3.14159265358979);
const int x_[8]={0,1,1,1,0,-1,-1,-1};
const int y_[8]={1,1,0,-1,-1,-1,0,1};
const int N=35,M=35,K=1000010;
int n,m,s[N][M]={},to[N][M]={},x[K]={},y[K]={},tot=-1;
bool flag=false,ok[N][M]={};
void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&s[i][j]);
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			scanf("%d",&to[i][j]);
}
void print_graph()
{
	cout<<"------------------"<<endl;
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
			cout<<s[i][j]<<' ';
		cout<<endl;
	}
	cout<<"tot="<<tot<<endl;
	for(int i=0;i<=tot;++i)
		cout<<x[i]<<' '<<y[i]<<endl;
	cout<<"------------------"<<endl;
}
bool check()
{
	for(int i=1;i<=n;++i)
		for(int j=1;j<=m;++j)
			if(s[i][j]!=to[i][j])
				return false;
	return true;
}
void move_around(int sx,int sy,int ex,int ey)
{
	int px[N*M]={},py[N*M]={},f[N*M]={},head=0,tail=0;
	bool in[N][M]={};
	++tail;
	in[sx][sy]=true;
	px[tail]=sx;
	py[tail]=sy;
	while(head!=tail)
	{
		++head;
		int x1=px[head],y1=py[head];
		for(int i=0;i<8;++i)
		{
			int tx=x1+x_[i],ty=y1+y_[i];
			if(ok[tx][ty] || in[tx][ty])
				continue;
			++tail;
			in[tx][ty]=true;
			px[tail]=tx;
			py[tail]=ty;
			f[tail]=head;
			if(tx==ex && ty==ey)
			{
				int pos=f[tail],stx[N*M]={},sty[N*M]={},top=0;
				while(f[pos])
				{
					++top;
					stx[top]=px[pos];
					sty[top]=py[pos];
					pos=f[pos];
				}
				for(int t=top;t>=1;--t)
				{
					++tot;
					x[tot]=stx[t];
					y[tot]=sty[t];
					swap(s[x[tot-1]][y[tot-1]],s[x[tot]][y[tot]]);
				}
				return;
			}
		}
	}
}
inline int abs(int x)
{
	return x>=0 ? x : -x;
}
void move_to(int space_x,int space_y,int sx,int sy,int ex,int ey)
{
	//cout<<"space_x="<<space_x<<" space_y="<<space_y;
	//cout<<"sx="<<sx<<" sy="<<sy<<" ex="<<ex<<" ey="<<ey<<endl;
	const int S=N*M*8;
	int nx[S]={},ny[S]={},rx[S]={},ry[S]={},f[S]={},head=0,tail=0;
	static bool in[N][M][N][M]={};
	++tail;
	in[sx][sy][space_x][space_y]=true;
	rx[tail]=space_x,ry[tail]=space_y,nx[tail]=sx,ny[tail]=sy;
	while(head!=tail)
	{
		++head;
		int nowx=nx[head],nowy=ny[head],spacex=rx[head],spacey=ry[head];
		for(int i=0;i<8;++i)
		{
			int nspacex=spacex+x_[i],nspacey=spacey+y_[i];
			int nnowx=nowx,nnowy=nowy;
			if(nspacex==nowx && nspacey==nowy)
				nnowx=spacex,nnowy=spacey;
			if(ok[nnowx][nnowy] || ok[nspacex][nspacey]
			|| in[nnowx][nnowy][nspacex][nspacey])
				continue;
			if(max(abs(nnowx-nspacex),abs(nnowy-nspacey))>1)
				continue;
			++tail;
			in[nnowx][nnowy][nspacex][nspacey]=true;
			rx[tail]=nspacex,ry[tail]=nspacey;
			nx[tail]=nnowx,ny[tail]=nnowy;
			f[tail]=head;
			if(nx[tail]==ex && ny[tail]==ey)
			{
				int pos=tail,stx[N*M*8]={},sty[N*M*8]={},top=0;
				while(f[pos])
				{
					++top;
					stx[top]=rx[pos];
					sty[top]=ry[pos];
					pos=f[pos];
				}
				//cout<<"top="<<top<<endl;
				for(int t=top;t>=1;--t)
				{
					//print_graph();
					++tot;
					x[tot]=stx[t];
					y[tot]=sty[t];
					swap(s[x[tot-1]][y[tot-1]],s[x[tot]][y[tot]]);
					//print_graph();
				}
				for(int t=1;t<=tail;++t)
					in[nx[t]][ny[t]][rx[t]][ry[t]]=false;
				return;
			}
		}
	}
}
bool adjust(int xto,int yto)
{
	//cout<<"xto="<<xto<<" yto="<<yto<<endl;
	int x1=0,y1=0;
	for(int i=1;i<=n && !x1;++i)
		for(int j=1;j<=m && !y1;++j)
			if(!ok[i][j] && (i!=x[tot] || j!=y[tot]) && s[i][j]==to[xto][yto])
				x1=i,y1=j;
	//cout<<"x1="<<x1<<" y1="<<y1<<endl;
	if(!x1 && !y1)
	{
		tot=-1;
		return false;
	}
	//cout<<"x[tot]="<<x[tot]<<" y[tot]="<<y[tot]<<endl;
	move_around(x[tot],y[tot],x1,y1);
	//cout<<"tot="<<tot<<endl;
	//cout<<"x[tot]="<<x[tot]<<" y[tot]="<<y[tot]<<endl;
	move_to(x[tot],y[tot],x1,y1,xto,yto);
	return true;
}
void work()
{
	if(n>m)
	{
		for(int i=1;i<=n;++i)
			for(int j=i;j<=n;++j)
				swap(s[i][j],s[j][i]),swap(to[i][j],to[j][i]);
		flag=true;
		swap(n,m);
	}
	for(int i=0;i<=m+1;++i)
		ok[0][i]=ok[n+1][i]=true;
	for(int i=0;i<=n+1;++i)
		ok[i][0]=ok[i][m+1]=true;
	if(n==1)
	{
		int c[M]={};
		for(int i=1;i<=m;++i)
		{
			copy(s[1]+1,s[1]+m+1,c+1);
			for(int j=i+1;j<=m;++j)
			{
				swap(s[1][j],s[1][j-1]);
				if(check())
				{
					for(int k=i;k<=j;++k)
						++tot,x[tot]=1,y[tot]=k;
					return;
				}
			}
			copy(c+1,c+m+1,s[1]+1);
			for(int j=i-1;j>=1;--j)
			{
				swap(s[1][j],s[1][j+1]);
				if(check())
				{
					for(int k=i;k>=j;--k)
						++tot,x[tot]=1,y[tot]=k;
					return;
				}
			}
			copy(c+1,c+m+1,s[1]+1);
		}
	}
	else
	{
		++tot;
		int toc=to[n][m];
		for(int i=1;i<=n && !x[tot];++i)
			for(int j=1;j<=m && !y[tot];++j)
				if(s[i][j]==toc)
				{
					x[tot]=i;
					y[tot]=j;
				}
		for(int i=1;i<=n-2;++i)
			for(int j=1;j<=m;++j)
			{
				if(s[i][j]!=to[i][j])
				{
					if(!adjust(i,j))
						return;
				}
				ok[i][j]=true;
			}
		for(int j=1;j<=m;++j)
		{
			if(s[n-1][j]!=to[n-1][j])
			{
				if(!adjust(n-1,j))
					return;
			}
			//print_graph();
			ok[n-1][j]=true;
			if(s[n][j]!=to[n][j])
			{
				if(!adjust(n,j))
					return;
			}
			ok[n][j]=true;
			//print_graph();
		}
	}
}
void print()
{
	printf("%d\n",tot);
	for(int i=0;i<=tot;++i)
		if(flag)
			printf("%d %d\n",y[i],x[i]);
		else
			printf("%d %d\n",x[i],y[i]);
}
int main()
{
	init();
	work();
	print();
	return 0;
}


#undef NDEBUG
#ifdef KUVIMAN
#define _GLIBCXX_DEBUG
#endif

#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cassert>
#include <ctime>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <bitset>
#include <algorithm>
#include <utility>
#include <numeric>
#include <functional>

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i, l, r) for (int i = int(l); i < int(r); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(x, y) make_pair((x), (y))
#define ft first
#define sc second
#define X first
#define Y second

using namespace std;

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

const int INF = int(1e9);
const li INF64 = li(1e18);
const ld EPS = 1e-9, PI = acosl(ld(-1));

int sign(int x) {
	if (x < 0) return -1;
	if (x > 0) return +1;
	throw;
}

const int N = 33;
int n, m;
int a[N][N], b[N][N];

pt pos[N][N], who[N][N];

vector<pt> ans;

void step(pt a, pt b) {
	swap(who[a.X][a.Y], who[b.X][b.Y]);
	pos[who[a.X][a.Y].X][who[a.X][a.Y].Y] = a;
	pos[who[b.X][b.Y].X][who[b.X][b.Y].Y] = b;
	ans.pb(b);
}

void moveTo(int x, int y) {
	pt& myPos = pos[0][0];
	while (myPos.X != x)
		step(myPos, pt(myPos.X + sign(x - myPos.X), myPos.Y));
	while (myPos.Y != y)
		step(myPos, pt(myPos.X, myPos.Y + sign(y - myPos.Y)));
}

void doSwap(pt a, pt b) {
	pt c = pos[0][0];
	step(c, a);
	step(a, b);
	step(b, c);
}

void moveX(pt from, int dx) {
	if (from.Y != 0)
		moveTo(from.X, from.Y - 1);
	else {
		moveTo(0, 1);
		moveTo(from.X, 1);
	}
	doSwap(from, pt(from.X + dx, from.Y));
	if (from.Y == 0)
		moveTo(0, 1);
	moveTo(0, 0);
}

void moveY(pt from, int dy) {
	if (from.X != 0)
		moveTo(from.X - 1, from.Y);
	else {
		moveTo(1, 0);
		moveTo(1, from.Y);
	}
	doSwap(from, pt(from.X, from.Y + dy));
	if (from.X == 0)
		moveTo(1, 0);
	moveTo(0, 0);
}

void place(pt from, pt to) {
	while (from.X != to.X) {
		moveX(from, sign(to.X - from.X));
		from.X += sign(to.X - from.X);
	}
	while (from.Y != to.Y) {
		moveY(from, sign(to.Y - from.Y));
		from.Y += sign(to.Y - from.Y);
	}
}

int cur[N][N];
void clear() {
	forn(i, n)
		forn(j, m)
			cur[i][j] = a[i][j];
}
bool ok() {
	forn(i, n)
		forn(j, m)
			if (cur[i][j] != b[i][j])
				return false;
	return true;
}

bool check() {
	clear();
	forn(i, sz(ans) - 1) {
		pt a = ans[i], b = ans[i + 1];
		swap(cur[a.X][a.Y], cur[b.X][b.Y]);
	}
/*	forn(i, n) {
		forn(j, m)
			cerr << cur[i][j] << ' ';
		cerr << endl;
	}*/
	return ok();
}

#ifdef KUVIMAN
//#define GEN
#endif

int buf[N * N];
bool solve() {
#ifdef GEN
	n = m = 30;
	forn(i, n * m)
		buf[i] = rand() % 10;
	forn(i, n)
		forn(j, m)
			a[i][j] = buf[i * m + j];
	random_shuffle(buf, buf + n * m);
	forn(i, n)
		forn(j, m)
			b[i][j] = buf[i * m + j];

	cerr << n << ' ' << m << endl;
	forn(i, n) {
		forn(j, m)
			cerr << a[i][j] << ' ';
		cerr << endl;
	}
	forn(i, n) {
		forn(j, m)
			cerr << b[i][j] << ' ';
		cerr << endl;
	}

#else
	if (scanf("%d%d", &n, &m) != 2)
		return false;
	forn(i, n)
		forn(j, m)
			assert(scanf("%d", &a[i][j]) == 1);
	forn(i, n)
		forn(j, m)
			assert(scanf("%d", &b[i][j]) == 1);
#endif

	int in = n, im = m;

	map<int,queue<pt> > q;

	if (n == 1 || m == 1) {
		if (n == 1) {
			forn(from, m)
				forn(to, m) {
					clear();
					ans.clear();
					for (int j = from; j != to; j += sign(to - j))
						swap(cur[0][j], cur[0][j + sign(to - j)]);
					if (ok()) {
						for (int j = from; j != to; j += sign(to - j))
							ans.pb(pt(0, j));
						ans.pb(pt(0, to));
						goto printAns;
					}
				}
			puts("-1");
		} else {
			forn(from, n)
				forn(to, n) {
					clear();
					ans.clear();
					for (int i = from; i != to; i += sign(to - i))
						swap(cur[i][0], cur[i + sign(to - i)][0]);
					if (ok()) {
						for (int i = from; i != to; i += sign(to - i))
							ans.pb(pt(i, 0));
						ans.pb(pt(to, 0));
						goto printAns;
					}
				}
			puts("-1");
		}
		return true;
	}
	forn(i, n)
		forn(j, m)
			q[a[i][j]].push(pt(i, j));
	forn(i, n)
		forn(j, m) {
			if (q[b[i][j]].empty()) {
				puts("-1");
				return true;
			}
			pos[i][j] = q[b[i][j]].front();
			who[pos[i][j].X][pos[i][j].Y] = pt(i, j);
			q[b[i][j]].pop();
		}

	ans.clear();
	ans.pb(pos[0][0]);
	moveTo(0, 0);
	while (n != 1 || m != 1) {
		if (n < m) {
			forn(i, n) {
			//	cerr << "MOVE FROM " << pos[i][m - 1].X << ' ' << pos[i][m - 1].Y << " to " << i << ' ' << m - 1 << endl;
				if (i == 0 && pos[i][m - 1].Y == 0) {
					place(pos[i][m - 1], pt(1, 0));
					doSwap(pt(1, 0), pt(0, 1));
				} else
    				place(pos[i][m - 1], pt(i, pos[i][m - 1].Y));
    			place(pos[i][m - 1], pt(i, m - 1));
			//	cerr << sz(ans) << endl;
			}
			m--;
			//cerr << "M-- " << sz(ans) << endl;
		} else {
			forn(j, m) {
			//	cerr << "MOVE FROM " << pos[n - 1][j].X << ' ' << pos[n - 1][j].Y << " to " << n - 1 << ' ' << j << endl;
				if (pos[n - 1][j].X == 0 && j == 0) {
					place(pos[n - 1][j], pt(0, 1));
					doSwap(pt(1, 0), pt(0, 1));
				} else
					place(pos[n - 1][j], pt(pos[n - 1][j].X, j));
				place(pos[n - 1][j], pt(n - 1, j));
			//	cerr << sz(ans) << endl;
			}
			n--;
			//cerr << "N-- " << sz(ans) << endl;
		}
		moveTo(0, 0);
	}

	n = in, m = im;

printAns:
	printf("%d\n", sz(ans) - 1);
	forn(i, sz(ans)) {
		printf("%d %d\n", ans[i].X + 1, ans[i].Y + 1);
	}

	assert(check());
	//cerr << sz(ans) << endl;

	return true;
}

int main() {
#ifdef KUVIMAN
	assert(freopen("input.txt", "rt", stdin));
	assert(freopen("output.txt", "wt", stdout));
#endif

	cout << setprecision(10) << fixed;
	cerr << setprecision(5) << fixed;

	while (solve()) {}
//	solve();

#ifdef KUVIMAN
	cerr << "== TIME : " << clock() << " ==" << endl;
#endif
	return 0;
}


#undef NDEBUG
#ifdef KUVIMAN
#define _GLIBCXX_DEBUG
#endif

#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cassert>
#include <ctime>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <bitset>
#include <algorithm>
#include <utility>
#include <numeric>
#include <functional>

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i, l, r) for (int i = int(l); i < int(r); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(x, y) make_pair((x), (y))
#define ft first
#define sc second
#define X first
#define Y second

using namespace std;

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

const int INF = int(1e9);
const li INF64 = li(1e18);
const ld EPS = 1e-9, PI = acosl(ld(-1));

int sign(int x) {
	if (x < 0) return -1;
	if (x > 0) return +1;
	throw;
}

const int N = 33;
int n, m;
int a[N][N], b[N][N];

pt pos[N][N], who[N][N];

vector<pt> ans;

void step(pt a, pt b) {
	swap(who[a.X][a.Y], who[b.X][b.Y]);
	pos[who[a.X][a.Y].X][who[a.X][a.Y].Y] = a;
	pos[who[b.X][b.Y].X][who[b.X][b.Y].Y] = b;
	ans.pb(b);
}

void moveTo(int x, int y) {
	pt& myPos = pos[0][0];
	while (myPos.X != x)
		step(myPos, pt(myPos.X + sign(x - myPos.X), myPos.Y));
	while (myPos.Y != y)
		step(myPos, pt(myPos.X, myPos.Y + sign(y - myPos.Y)));
}

void doSwap(pt a, pt b) {
	pt c = pos[0][0];
	step(c, a);
	step(a, b);
	step(b, c);
}

void moveX(pt from, int dx) {
	if (from.Y != 0)
		moveTo(from.X, from.Y - 1);
	else {
		moveTo(0, 1);
		moveTo(from.X, 1);
	}
	doSwap(from, pt(from.X + dx, from.Y));
	if (from.Y == 0)
		moveTo(0, 1);
	moveTo(0, 0);
}

void moveY(pt from, int dy) {
	if (from.X != 0)
		moveTo(from.X - 1, from.Y);
	else {
		moveTo(1, 0);
		moveTo(1, from.Y);
	}
	doSwap(from, pt(from.X, from.Y + dy));
	if (from.X == 0)
		moveTo(1, 0);
	moveTo(0, 0);
}

void place(pt from, pt to) {
	while (from.X != to.X) {
		moveX(from, sign(to.X - from.X));
		from.X += sign(to.X - from.X);
	}
	while (from.Y != to.Y) {
		moveY(from, sign(to.Y - from.Y));
		from.Y += sign(to.Y - from.Y);
	}
}

int cur[N][N];
void clear() {
	forn(i, n)
		forn(j, m)
			cur[i][j] = a[i][j];
}
bool ok() {
	forn(i, n)
		forn(j, m)
			if (cur[i][j] != b[i][j])
				return false;
	return true;
}

bool check() {
	clear();
	forn(i, sz(ans) - 1) {
		pt a = ans[i], b = ans[i + 1];
		swap(cur[a.X][a.Y], cur[b.X][b.Y]);
	}
	return ok();
}

bool solve() {
	if (scanf("%d%d", &n, &m) != 2)
		return false;
	forn(i, n)
		forn(j, m)
			assert(scanf("%d", &a[i][j]) == 1);
	forn(i, n)
		forn(j, m)
			assert(scanf("%d", &b[i][j]) == 1);

	map<int,queue<pt> > q;

	if (n == 1 || m == 1) {
		if (n == 1) {
			forn(from, m)
				forn(to, m) {
					clear();
					ans.clear();
					for (int j = from; j != to; j += sign(to - j))
						swap(cur[0][j], cur[0][j + sign(to - j)]);
					if (ok()) {
						for (int j = from; j != to; j += sign(to - j))
							ans.pb(pt(0, j));
						ans.pb(pt(0, to));
						goto printAns;
					}
				}
			puts("-1");
		} else {
			forn(from, n)
				forn(to, n) {
					clear();
					ans.clear();
					for (int i = from; i != to; i += sign(to - i))
						swap(cur[i][0], cur[i + sign(to - i)][0]);
					if (ok()) {
						for (int i = from; i != to; i += sign(to - i))
							ans.pb(pt(i, 0));
						ans.pb(pt(to, 0));
						goto printAns;
					}
				}
			puts("-1");
		}
		return true;
	}
	forn(i, n)
		forn(j, m)
			q[a[i][j]].push(pt(i, j));
	forn(i, n)
		forn(j, m) {
			if (q[b[i][j]].empty()) {
				puts("-1");
				return true;
			}
			pos[i][j] = q[b[i][j]].front();
			who[pos[i][j].X][pos[i][j].Y] = pt(i, j);
			q[b[i][j]].pop();
		}

	ans.clear();
	ans.pb(pos[0][0]);
	moveTo(0, 0);
	while (n != 1 || m != 1) {
		if (n < m) {
			forn(i, n) {
				place(pos[i][m - 1], pt(i, pos[i][m - 1].Y));
				place(pos[i][m - 1], pt(i, m - 1));
			}
			m--;
		} else {
			forn(j, m) {
				place(pos[n - 1][j], pt(pos[n - 1][j].X, j));
				place(pos[n - 1][j], pt(n - 1, j));
			}
			n--;
		}
		moveTo(0, 0);
	}

printAns:
	assert(check());
	printf("%d\n", sz(ans));
	forn(i, sz(ans)) {
		printf("%d %d\n", ans[i].X + 1, ans[i].Y + 1);
	}

	return true;
}

int main() {
#ifdef KUVIMAN
	assert(freopen("input.txt", "rt", stdin));
//	assert(freopen("output.txt", "wt", stdout));
#endif

	cout << setprecision(10) << fixed;
	cerr << setprecision(5) << fixed;

	while (solve()) {}

#ifdef KUVIMAN
	cerr << "== TIME : " << clock() << " ==" << endl;
#endif
	return 0;
}


#undef NDEBUG
#ifdef KUVIMAN
#define _GLIBCXX_DEBUG
#endif

#include <iostream>
#include <iomanip>
#include <sstream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <cstring>
#include <cassert>
#include <ctime>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <bitset>
#include <algorithm>
#include <utility>
#include <numeric>
#include <functional>

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i, l, r) for (int i = int(l); i < int(r); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(x, y) make_pair((x), (y))
#define ft first
#define sc second
#define X first
#define Y second

using namespace std;

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

const int INF = int(1e9);
const li INF64 = li(1e18);
const ld EPS = 1e-9, PI = acosl(ld(-1));

int sign(int x) {
	if (x < 0) return -1;
	if (x > 0) return +1;
	throw;
}

const int N = 33;
int n, m;
int a[N][N], b[N][N];

pt pos[N][N], who[N][N];

vector<pt> ans;

void step(pt a, pt b) {
	swap(who[a.X][a.Y], who[b.X][b.Y]);
	pos[who[a.X][a.Y].X][who[a.X][a.Y].Y] = a;
	pos[who[b.X][b.Y].X][who[b.X][b.Y].Y] = b;
	ans.pb(b);
}

void moveTo(int x, int y) {
	pt& myPos = pos[0][0];
	while (myPos.X != x)
		step(myPos, pt(myPos.X + sign(x - myPos.X), myPos.Y));
	while (myPos.Y != y)
		step(myPos, pt(myPos.X, myPos.Y + sign(y - myPos.Y)));
}

void doSwap(pt a, pt b) {
	pt c = pos[0][0];
	step(c, a);
	step(a, b);
	step(b, c);
}

void moveX(pt from, int dx) {
	if (from.Y != 0)
		moveTo(from.X, from.Y - 1);
	else {
		moveTo(0, 1);
		moveTo(from.X, 1);
	}
	doSwap(from, pt(from.X + dx, from.Y));
	if (from.Y == 0)
		moveTo(0, 1);
	moveTo(0, 0);
}

void moveY(pt from, int dy) {
	if (from.X != 0)
		moveTo(from.X - 1, from.Y);
	else {
		moveTo(1, 0);
		moveTo(1, from.Y);
	}
	doSwap(from, pt(from.X, from.Y + dy));
	if (from.X == 0)
		moveTo(1, 0);
	moveTo(0, 0);
}

void place(pt from, pt to) {
	while (from.X != to.X) {
		moveX(from, sign(to.X - from.X));
		from.X += sign(to.X - from.X);
	}
	while (from.Y != to.Y) {
		moveY(from, sign(to.Y - from.Y));
		from.Y += sign(to.Y - from.Y);
	}
}

int cur[N][N];
void clear() {
	forn(i, n)
		forn(j, m)
			cur[i][j] = a[i][j];
}
bool ok() {
	forn(i, n)
		forn(j, m)
			if (cur[i][j] != b[i][j])
				return false;
	return true;
}

bool check() {
	clear();
	forn(i, sz(ans) - 1) {
		pt a = ans[i], b = ans[i + 1];
		swap(cur[a.X][a.Y], cur[b.X][b.Y]);
	}
	return ok();
}

bool solve() {
	if (scanf("%d%d", &n, &m) != 2)
		return false;
	forn(i, n)
		forn(j, m)
			assert(scanf("%d", &a[i][j]) == 1);
	forn(i, n)
		forn(j, m)
			assert(scanf("%d", &b[i][j]) == 1);

	map<int,queue<pt> > q;

	if (n == 1 || m == 1) {
		if (n == 1) {
			forn(from, m)
				forn(to, m) {
					clear();
					ans.clear();
					for (int j = from; j != to; j += sign(to - j))
						swap(cur[0][j], cur[0][j + sign(to - j)]);
					if (ok()) {
						for (int j = from; j != to; j += sign(to - j))
							ans.pb(pt(0, j));
						ans.pb(pt(0, to));
						goto printAns;
					}
				}
			puts("-1");
		} else {
			forn(from, n)
				forn(to, n) {
					clear();
					ans.clear();
					for (int i = from; i != to; i += sign(to - i))
						swap(cur[i][0], cur[i + sign(to - i)][0]);
					if (ok()) {
						for (int i = from; i != to; i += sign(to - i))
							ans.pb(pt(i, 0));
						ans.pb(pt(to, 0));
						goto printAns;
					}
				}
			puts("-1");
		}
		return true;
	}
	forn(i, n)
		forn(j, m)
			q[a[i][j]].push(pt(i, j));
	forn(i, n)
		forn(j, m) {
			if (q[b[i][j]].empty()) {
				puts("-1");
				return true;
			}
			pos[i][j] = q[b[i][j]].front();
			who[pos[i][j].X][pos[i][j].Y] = pt(i, j);
			q[b[i][j]].pop();
		}

	ans.clear();
	ans.pb(pos[0][0]);
	moveTo(0, 0);
	while (n != 1 || m != 1) {
		if (n < m) {
			forn(i, n) {
				//cerr << "MOVE FROM " << pos[i][m - 1].X << ' ' << pos[i][m - 1].Y << " to " << i << ' ' << m - 1 << endl;
				place(pos[i][m - 1], pt(i, pos[i][m - 1].Y));
				place(pos[i][m - 1], pt(i, m - 1));
				//cerr << sz(ans) << endl;
			}
			m--;
			//cerr << "M-- " << sz(ans) << endl;
		} else {
			forn(j, m) {
				//cerr << "MOVE FROM " << pos[n - 1][j].X << ' ' << pos[n - 1][j].Y << " to " << n - 1 << ' ' << j << endl;
				place(pos[n - 1][j], pt(pos[n - 1][j].X, j));
				place(pos[n - 1][j], pt(n - 1, j));
				//cerr << sz(ans) << endl;
			}
			n--;
			//cerr << "N-- " << sz(ans) << endl;
		}
		moveTo(0, 0);
	}

printAns:
	assert(check());
	printf("%d\n", sz(ans) - 1);
	forn(i, sz(ans)) {
		printf("%d %d\n", ans[i].X + 1, ans[i].Y + 1);
	}

	return true;
}

int main() {
#ifdef KUVIMAN
	assert(freopen("input.txt", "rt", stdin));
//	assert(freopen("output.txt", "wt", stdout));
#endif

	cout << setprecision(10) << fixed;
	cerr << setprecision(5) << fixed;

	while (solve()) {}

#ifdef KUVIMAN
	cerr << "== TIME : " << clock() << " ==" << endl;
#endif
	return 0;
}


#include <ctime>
#include <cstdio>
#include <cstdlib>
const int maxn = 32, maxc = 901, maxs = 1000001, dx[] = {-1, -1, -1, 0, 0, 1, 1, 1}, dy[] = {-1, 0, 1, -1, 1, -1, 0, 1};
int n, m, s[maxn][maxn], t[maxn][maxn], cnt[maxc], ans, out[maxs][2];
bool vis[maxn][maxn], trans;
void swap(int &x, int &y)
{
	int t = x;
	x = y;
	y = t;
}
int abs(int x)
{
	return x < 0 ? -x : x;
}
void move(int x, int y)//move (x2, y2) to (x, y) start at (x1, y1)
{
	int x1 = out[ans - 1][0], y1 = out[ans - 1][1], x2 = 0, y2, xx, yy, xxx, yyy, dist, tmp;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			if(!vis[i][j] && s[i][j] == t[x][y] && !(i == x1 && j == y1))
			{
				x2 = i;
				y2 = j;
			}
	for(dist = abs(x2 - x1) + abs(y2 - y1); dist > 1; dist = tmp)
	{
		for(int i = 0; i < 8; ++i)
		{
			xx = x1 + dx[i];
			yy = y1 + dy[i];
			tmp = abs(xx - x2) + abs(yy - y2);
			if(!vis[xx][yy] && tmp < dist && !(xx == x2 && yy == y2))
				break;
		}
		swap(s[xx][yy], s[x1][y1]);
		out[ans][0] = x1 = xx;
		out[ans++][1] = y1 = yy;
	}
	for(dist = abs(x2 - x) + abs(y2 - y); !(x2 == x && y2 == y); dist = tmp)
	{
		int i, last = -1;
		while(1)
		{
			i = rand() & 7;//be careful! infinite loop!
			if(i + last == 7)
				continue;
			xx = x1 + dx[i];
			yy = y1 + dy[i];
			if(xx == x2 && yy == y2)
			{
				xxx = x1;
				yyy = y1;
			}
			else
			{
				xxx = x2;
				yyy = y2;
			}
			tmp = abs(xxx - x) + abs(yyy - y);
			if(!vis[xx][yy] && abs(xx - xxx) <= 1 && abs(yy - yyy) <= 1 && tmp <= dist)
				break;
		}
		swap(s[xx][yy], s[x1][y1]);
		out[ans][0] = x1 = xx;
		out[ans++][1] = y1 = yy;
		x2 = xxx;
		y2 = yyy;
		last = i;
	}
	vis[x][y] = 1;
}
int main()
{
	srand(time(0));
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
		{
			scanf("%d", &s[i][j]);
			++cnt[s[i][j]];
		}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
		{
			scanf("%d", &t[i][j]);
			--cnt[t[i][j]];
		}
	for(int i = 0; i < maxc; ++i)
		if(cnt[i])
		{
			puts("-1");
			return 0;
		}
	if(n > m)
	{
		trans = 1;
		for(int i = 1; i <= n; ++i)
			for(int j = i + 1; j <= n; ++j)
			{
				swap(s[i][j], s[j][i]);
				swap(t[i][j], t[j][i]);
			}
		swap(n, m);
	}
	if(n == 1)
	{
		int l, r;
		bool flag;
		for(l = 1; s[1][l] == t[1][l]; ++l);
		for(r = m; s[1][r] == t[1][r]; --r);
		flag = s[1][l] == t[1][r];
		for(int i = l + 1; i <= r; ++i)
			flag &= s[1][i] == t[1][i - 1];
		if(flag)
		{
			printf("%d\n", r - l);
			for(int i = l; i <= r; ++i)
			{
				int x = 1, y = i;
				if(trans)
					swap(x, y);
				printf("%d %d\n", x, y);
			}
			return 0;
		}
		flag = s[1][r] == t[1][l];
		for(int i = l; i < r; ++i)
			flag &= s[1][i] == t[1][i + 1];
		if(flag)
		{
			printf("%d\n", r - l);
			for(int i = r; i >= l; --i)
			{
				int x = 1, y = i;
				if(trans)
					swap(x, y);
				printf("%d %d\n", x, y);
			}
			return 0;
		}
		puts("-1");
		return 0;
	}
	for(int i = 0; i <= n + 1; ++i)
		vis[i][0] = vis[i][m + 1] = 1;
	for(int i = 1; i <= m; ++i)
		vis[0][i] = vis[n + 1][i] = 1;
	for(int i = 1; i <= n && !ans; ++i)
		for(int j = 1; j <= m && !ans; ++j)
			if(s[i][j] == t[n][m])
			{
				out[ans][0] = i;
				out[ans++][1] = j;
			}
	for(int i = 1; i < n - 1; ++i)
		for(int j = 1; j <= m; ++j)
			move(i, j);
	for(int i = 1; i < m; ++i)
	{
		move(n - 1, i);
		move(n, i);
	}
	move(n - 1, m);
	printf("%d\n", ans - 1);
	for(int i = 0; i < ans; ++i)
	{
		if(trans)
			swap(out[i][0], out[i][1]);
		printf("%d %d\n", out[i][0], out[i][1]);
	}
	return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> pii;

vector<pii> ans;
vector<pii> path;

int n, m, px, py, swaped, s[33][33], t[33][33], vis[33][33], aux[33][33], cnts[999], cntt[999];

int dx[] = {1, 1, -1, -1, 0, 1, 0, -1};
int dy[] = {1, -1, 1, -1, 1, 0, -1, 0};

void change() {
	if(m >= n) return;
	swaped ^= 1;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = s[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) s[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = t[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) t[i][j] = aux[i][j];
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) aux[j][i] = vis[i][j];
	for(int i=0;i<m;i++) for(int j=0;j<n;j++) vis[i][j] = aux[i][j];
	swap(n, m);
	swap(px, py);
}

int mod(int x) { return x > 0 ? x : -x; }

void add(int x, int y) {
	if(swaped) ans.push_back(pii(y, x));
	else ans.push_back(pii(x, y));
}

pii get(int c) {
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(!vis[i][j] && s[i][j]==c) return pii(i, j);
}

int dir(int sx, int sy, int x, int y) {
	int mi, d=1e9;
	for(int i=0;i<8;i++) {
		int nx = sx + dx[i];
		int ny = sy + dy[i];
		if(nx < 0 || nx >= n || ny < 0 || ny >= m || vis[nx][ny]) continue;
		int nd = mod(x-nx) + mod(y-ny);
		if(nd < d) d = nd, mi = i;
	}
	return mi;
}

void move(int x, int y) {
	while(x != px || y != py) {
		int mi = dir(px, py, x, y);
		int nx = px + dx[mi];
		int ny = py + dy[mi];
		add(nx, ny);
		swap(s[px][py], s[nx][ny]);
		swap(vis[px][py], vis[nx][ny]);
		px = nx; py = ny;
	}
}

void correct(int x, int y) {
	pii p = get(t[x][y]);
	int sx = p.first;
	int sy = p.second;
	path.clear();
	path.push_back(pii(sx, sy));
	vis[px][py]=0;
	while(sx != x || sy != y) {
		int mi = dir(sx, sy, x, y);
		sx = sx + dx[mi];
		sy = sy + dy[mi];
		path.push_back(pii(sx, sy));
	}
	vis[px][py]=1;
	vis[p.first][p.second] = 1;
	for(int i=0;i<path.size()-1;i++) {
		move(path[i+1].first, path[i+1].second);
		add(path[i].first, path[i].second);
		swap(s[px][py], s[path[i].first][path[i].second]);
		px = path[i].first;
		py = path[i].second;
	}
}

int solve() {
	for(int i=0;i<999;i++) if(cnts[i]!=cntt[i]) return 0;
	change();
	if(n==1) {
		for(int i=0;i<m;i++) for(int j=0;j<m;j++) {
			px=0, py=i;
			ans.clear();
			add(0, i);
			move(0, j);
			int k;
			for(k=0;k<m;k++) if(s[0][k] != t[0][k]) break;
			if(k==m) return 1;
			move(0, i);
		}
		return 0;
	}
	pii p = get(t[0][0]);
	px = p.first;
	py = p.second;
	vis[px][py] = 1;
	add(px, py);
	while(m > 2) {
		for(int i=0;i<n;i++) correct(i, m-1);
		m--;
		change();
	}
	move(1, 1);
	p = get(t[1][1]);
	move(p.first, p.second);
	vis[1][1]=1;
	move(1, 0);
	p = get(t[1][0]);
	move(p.first, p.second);
	move(0, 0);
	return 1;
}

int main() {
	cin>>n>>m;
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>s[i][j];
		cnts[s[i][j]]++;
	}
	for(int i=0;i<n;i++) for(int j=0;j<m;j++) {
		cin>>t[i][j];
		cntt[t[i][j]]++;
	}
	if(solve()) {
		cout << ans.size()-1 << endl;
		for(int i=0;i<ans.size();i++) cout << ans[i].first+1 << " " << ans[i].second+1 << endl;
	} else {
		cout << -1 << endl;
		return 0;
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <conio.h>
#include <map>
#include <cassert>
#include <cctype>
using namespace std;
typedef long long LL;
const int N = 35;
int n , m;
int a[N][N] , b[N][N];
int cnt[N * N] , d[N];

void solven() {
    int i , j , k;
    for (i = 1 ; i <= m ; ++ i) {
        int x = a[1][i];
        for (j = 1 ; j < i ; ++ j) {
            for (k = 1 ; k <= m ; ++ k)
                d[k] = a[1][k];
            for (k = i ; k > j ; -- k)
                d[k] = d[k - 1];
            d[j] = x;
            for (k = 1 ; k <= m ; ++ k)
                if (d[k] != b[1][k])
                    break;
            if (k > m) {
                printf("%d\n" , i - j);
                for (k = i ; k >= j ; -- k)
                    printf("%d %d\n" , 1 , k);
                return;
            }
        }
        for (j = i + 1 ; j <= m ; ++ j) {
            for (k = 1 ; k <= m ; ++ k)
                d[k] = a[1][k];
            for (k = i ; k < j ; ++ k)
                d[k] = d[k + 1];
            d[j] = x;
            for (k = 1 ; k <= m ; ++ k)
                if (d[k] != b[1][k])
                    break;
            if (k > m) {
                printf("%d\n" , j - i);
                for (k = i ; k <= j ; ++ k)
                    printf("%d %d\n" , 1 , k);
                return;
            }
        }
    }
    puts("-1");
}
void solvem() {
    int i , j , k;
    for (i = 1 ; i <= n ; ++ i) {
        int x = a[i][1];
        for (j = 1 ; j < i ; ++ j) {
            for (k = 1 ; k <= n ; ++ k)
                d[k] = a[k][1];
            for (k = i ; k > j ; -- k)
                d[k] = d[k - 1];
            d[j] = x;
            for (k = 1 ; k <= n ; ++ k)
                if (d[k] != b[k][1])
                    break;
            if (k > n) {
                printf("%d\n" , i - j);
                for (k = i ; k >= j ; -- k)
                    printf("%d %d\n" , k , 1);
                return;
            }
        }
        for (j = i + 1 ; j <= n ; ++ j) {
            for (k = 1 ; k <= n ; ++ k)
                d[k] = a[k][1];
            for (k = i ; k < j ; ++ k)
                d[k] = d[k + 1];
            d[j] = x;
            for (k = 1 ; k <= n ; ++ k)
                if (d[k] != b[k][1])
                    break;
            if (k > n) {
                printf("%d\n" , j - i);
                for (k = i ; k <= j ; ++ k)
                    printf("%d %d\n" , k , 1);
                return;
            }
        }
    }
    puts("-1");
}

vector< pair<int , int> > res;

void moveup(int x , int y) {
    int i = x - 1 , j , u , v;
    if (y > 1)
        j = y - 1;
    else
        j = y + 1;
    u = v = 1;
    while (v < j) {
        swap(a[u][v] , a[u][v + 1]);
        res.push_back(make_pair(u , v + 1));
        ++ v;
    }
    while (u < i) {
        swap(a[u][v] , a[u + 1][v]);
        res.push_back(make_pair(u + 1 , v));
        ++ u;
    }
    swap(a[i][j] , a[x][y]);
    res.push_back(make_pair(x , y));
    swap(a[x][y] , a[x - 1][y]);
    res.push_back(make_pair(x - 1 , y));
    swap(a[x - 1][y] , a[i][j]);
    res.push_back(make_pair(i , j));
    while (u > 1) {
        swap(a[u][v] , a[u - 1][v]);
        res.push_back(make_pair(u - 1 , v));
        -- u;
    }
    while (v > 1) {
        swap(a[u][v] , a[u][v - 1]);
        res.push_back(make_pair(u , v - 1));
        -- v;
    }
}

void moveleft(int x , int y) {
    int i , j = y - 1 , u , v;
    if (x > 1)
        i = x - 1;
    else
        i = x + 1;
    u = v = 1;
    while (u < i) {
        swap(a[u][v] , a[u + 1][v]);
        res.push_back(make_pair(u + 1 , v));
        ++ u;
    }
    while (v < j) {
        swap(a[u][v] , a[u][v + 1]);
        res.push_back(make_pair(u , v + 1));
        ++ v;
    }
    swap(a[i][j] , a[x][y]);
    res.push_back(make_pair(x , y));
    swap(a[x][y] , a[x][y - 1]);
    res.push_back(make_pair(x , y - 1));
    swap(a[x][y - 1] , a[i][j]);
    res.push_back(make_pair(i , j));
    while (v > 1) {
        swap(a[u][v] , a[u][v - 1]);
        res.push_back(make_pair(u , v - 1));
        -- v;
    }
    while (u > 1) {
        swap(a[u][v] , a[u - 1][v]);
        res.push_back(make_pair(u - 1 , v));
        -- u;
    }
}
void movedownleft(int x , int y) {
    int i = x , j = y - 1 , u , v;
    u = v = 1;
    while (u < i) {
        swap(a[u][v] , a[u + 1][v]);
        res.push_back(make_pair(u + 1 , v));
        ++ u;
    }
    while (v < j) {
        swap(a[u][v] , a[u][v + 1]);
        res.push_back(make_pair(u , v + 1));
        ++ v;
    }
    swap(a[i][j] , a[x][y]);
    res.push_back(make_pair(x , y));
    swap(a[x][y] , a[x + 1][y - 1]);
    res.push_back(make_pair(x + 1 , y - 1));
    swap(a[x + 1][y - 1] , a[i][j]);
    res.push_back(make_pair(i , j));
    while (v > 1) {
        swap(a[u][v] , a[u][v - 1]);
        res.push_back(make_pair(u , v - 1));
        -- v;
    }
    while (u > 1) {
        swap(a[u][v] , a[u - 1][v]);
        res.push_back(make_pair(u - 1 , v));
        -- u;
    }
}

void work() {
    int i , j , k , x , y;
    scanf("%d%d",&n,&m);
    for (i = 1 ; i <= n ; ++ i)
        for (j = 1 ; j <= m ; ++ j)
            scanf("%d",&a[i][j]) , ++ cnt[a[i][j]];
    for (i = 1 ; i <= n ; ++ i)
        for (j = 1 ; j <= m ; ++ j)
            scanf("%d",&b[i][j]) , -- cnt[b[i][j]];
    {
    for (i = 1 ; i <= 900 ; ++ i)
        if (cnt[i])
            break;
    if (i <= 900) {
        puts("-1");
        return;
    }
    if (n == 1) {
        solven();
        return;
    }
    if (m == 1) {
        solvem();
        return;
    }
    }
    x = y = -1;
    for (i = 1 ; i <= n ; ++ i)
        for (j = 1 ; j <= m ; ++ j)
            if (a[i][j] == b[1][1])
                x = i , y = j;
    assert(~x);
    assert(~y);
    res.push_back(make_pair(x , y));
    while (x > 1) {
        swap(a[x - 1][y] , a[x][y]);
        res.push_back(make_pair(x - 1 , y));
        -- x;
    }
    while (y > 1) {
        swap(a[x][y - 1] , a[x][y]);
        res.push_back(make_pair(x , y - 1));
        -- y;
    }
    for (i = n ; i > 0 ; -- i)
        for (j = m ; j > 0 ; -- j) {
            for (k = m * (i - 1) + j ; k > 0 ; -- k) {
                x = (k - 1) / m + 1 , y = (k - 1) % m + 1;
                if (a[x][y] == b[i][j])
                    break;
            }
            assert(k > 0);
            while (x < i && y > j) {
                movedownleft(x , y);
                ++ x , -- y;
            }
            while (x < i) {
                moveup(x + 1 , y);
                ++ x;
            }
            while (y < j) {
                moveleft(x , y + 1);
                ++ y;
            }
            while (y > j) {
                moveleft(x , y);
                -- y;
            }
        }
    printf("%d\n" , res.size() - 1);
    for (i = 0 ; i < res.size() ; ++ i)
        printf("%d %d\n" , res[i].first , res[i].second);
}

int main() {
    work();
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <conio.h>
#include <map>
#include <cassert>
#include <cctype>
using namespace std;
typedef long long LL;
const int N = 35;
int n , m;
int a[N][N] , b[N][N];
int cnt[N * N] , d[N];

void solven() {
    int i , j , k;
    for (i = 1 ; i <= m ; ++ i) {
        int x = a[1][i];
        for (j = 1 ; j < i ; ++ j) {
            for (k = 1 ; k <= m ; ++ k)
                d[k] = a[1][k];
            for (k = i ; k > j ; -- k)
                d[k] = d[k - 1];
            d[j] = x;
            for (k = 1 ; k <= m ; ++ k)
                if (d[k] != b[1][k])
                    break;
            if (k > m) {
                printf("%d\n" , i - j);
                for (k = i ; k >= j ; -- k)
                    printf("%d %d\n" , 1 , k);
                return;
            }
        }
        for (j = i + 1 ; j <= m ; ++ j) {
            for (k = 1 ; k <= m ; ++ k)
                d[k] = a[1][k];
            for (k = i ; k < j ; ++ k)
                d[k] = d[k + 1];
            d[j] = x;
            for (k = 1 ; k <= m ; ++ k)
                if (d[k] != b[1][k])
                    break;
            if (k > m) {
                printf("%d\n" , j - i);
                for (k = i ; k <= j ; ++ k)
                    printf("%d %d\n" , 1 , k);
                return;
            }
        }
    }
    puts("-1");
}
void solvem() {
    int i , j , k;
    for (i = 1 ; i <= n ; ++ i) {
        int x = a[i][1];
        for (j = 1 ; j < i ; ++ j) {
            for (k = 1 ; k <= n ; ++ k)
                d[k] = a[k][1];
            for (k = i ; k > j ; -- k)
                d[k] = d[k - 1];
            d[j] = x;
            for (k = 1 ; k <= n ; ++ k)
                if (d[k] != b[k][1])
                    break;
            if (k > n) {
                printf("%d\n" , i - j);
                for (k = i ; k >= j ; -- k)
                    printf("%d %d\n" , k , 1);
                return;
            }
        }
        for (j = i + 1 ; j <= n ; ++ j) {
            for (k = 1 ; k <= n ; ++ k)
                d[k] = a[k][1];
            for (k = i ; k < j ; ++ k)
                d[k] = d[k + 1];
            d[j] = x;
            for (k = 1 ; k <= n ; ++ k)
                if (d[k] != b[k][1])
                    break;
            if (k > n) {
                printf("%d\n" , j - i);
                for (k = i ; k <= j ; ++ k)
                    printf("%d %d\n" , k , 1);
                return;
            }
        }
    }
    puts("-1");
}

vector< pair<int , int> > res;

void moveup(int x , int y) {
    int i = x - 1 , j , u , v;
    if (y > 1)
        j = y - 1;
    else
        j = y + 1;
    u = v = 1;
    while (v < j) {
        swap(a[u][v] , a[u][v + 1]);
        res.push_back(make_pair(u , v + 1));
        ++ v;
    }
    while (u < i) {
        swap(a[u][v] , a[u + 1][v]);
        res.push_back(make_pair(u + 1 , v));
        ++ u;
    }
    swap(a[i][j] , a[x][y]);
    res.push_back(make_pair(x , y));
    swap(a[x][y] , a[x - 1][y]);
    res.push_back(make_pair(x - 1 , y));
    swap(a[x - 1][y] , a[i][j]);
    res.push_back(make_pair(i , j));
    while (u > 1) {
        swap(a[u][v] , a[u - 1][v]);
        res.push_back(make_pair(u - 1 , v));
        -- u;
    }
    while (v > 1) {
        swap(a[u][v] , a[u][v - 1]);
        res.push_back(make_pair(u , v - 1));
        -- v;
    }
}
void moveleft(int x , int y) {
    int i , j = y - 1 , u , v;
    if (x > 1)
        i = x - 1;
    else
        i = x + 1;
    u = v = 1;
    while (u < i) {
        swap(a[u][v] , a[u + 1][v]);
        res.push_back(make_pair(u + 1 , v));
        ++ u;
    }
    while (v < j) {
        swap(a[u][v] , a[u][v + 1]);
        res.push_back(make_pair(u , v + 1));
        ++ v;
    }
    swap(a[i][j] , a[x][y]);
    res.push_back(make_pair(x , y));
    swap(a[x][y] , a[x][y - 1]);
    res.push_back(make_pair(x , y - 1));
    swap(a[x][y - 1] , a[i][j]);
    res.push_back(make_pair(i , j));
    while (v > 1) {
        swap(a[u][v] , a[u][v - 1]);
        res.push_back(make_pair(u , v - 1));
        -- v;
    }
    while (u > 1) {
        swap(a[u][v] , a[u - 1][v]);
        res.push_back(make_pair(u - 1 , v));
        -- u;
    }
}
void movedownleft(int x , int y) {
    int i = x , j = y - 1 , u , v;
    u = v = 1;
    while (v < j) {
        swap(a[u][v] , a[u][v + 1]);
        res.push_back(make_pair(u , v + 1));
        ++ v;
    }
    while (u < i) {
        swap(a[u][v] , a[u + 1][v]);
        res.push_back(make_pair(u + 1 , v));
        ++ u;
    }
    swap(a[i][j] , a[x][y]);
    res.push_back(make_pair(x , y));
    swap(a[x][y] , a[x + 1][y - 1]);
    res.push_back(make_pair(x + 1 , y - 1));
    swap(a[x + 1][y - 1] , a[i][j]);
    res.push_back(make_pair(i , j));
    while (u > 1) {
        swap(a[u][v] , a[u - 1][v]);
        res.push_back(make_pair(u - 1 , v));
        -- u;
    }
    while (v > 1) {
        swap(a[u][v] , a[u][v - 1]);
        res.push_back(make_pair(u , v - 1));
        -- v;
    }
}

void work() {
    int i , j , k , x , y;
    scanf("%d%d",&n,&m);
    for (i = 1 ; i <= n ; ++ i)
        for (j = 1 ; j <= m ; ++ j)
            scanf("%d",&a[i][j]) , ++ cnt[a[i][j]];
    for (i = 1 ; i <= n ; ++ i)
        for (j = 1 ; j <= m ; ++ j)
            scanf("%d",&b[i][j]) , -- cnt[b[i][j]];
    {
    for (i = 1 ; i <= 900 ; ++ i)
        if (cnt[i])
            break;
    if (i <= 900) {
        puts("-1");
        return;
    }
    if (n == 1) {
        solven();
        return;
    }
    if (m == 1) {
        solvem();
        return;
    }
    }
    x = y = -1;
    for (i = 1 ; i <= n && !~x ; ++ i)
        for (j = 1 ; j <= m && !~x ; ++ j)
            if (a[i][j] == b[1][1])
                x = i , y = j;
    res.push_back(make_pair(x , y));
    while (x > 1) {
        swap(a[x - 1][y] , a[x][y]);
        res.push_back(make_pair(x - 1 , y));
        -- x;
    }
    while (y > 1) {
        swap(a[x][y - 1] , a[x][y]);
        res.push_back(make_pair(x , y - 1));
        -- y;
    }
    for (i = n ; i > 0 ; -- i)
        for (j = m ; j > 0 ; -- j) {
            for (k = m * (i - 1) + j ; k > 0 ; -- k) {
                x = (k - 1) / m + 1 , y = (k - 1) % m + 1;
                if (a[x][y] == b[i][j])
                    break;
            }
            assert(k > 0);
            while (y > j && x + y > i + j) {
                moveleft(x , y);
                -- y;
            }
            while (x < i && y > j) {
                movedownleft(x , y);
                ++ x , -- y;
            }
            while (y < j) {
                moveleft(x , y + 1);
                ++ y;
            }
            while (y > j) {
                moveleft(x , y);
                -- y;
            }
            while (x < i) {
                moveup(x + 1 , y);
                ++ x;
            }
        }
    printf("%d\n" , res.size() - 1);
    for (i = 0 ; i < res.size() ; ++ i)
        printf("%d %d\n" , res[i].first , res[i].second);
}

int main() {
    work();
    return 0;
}