AOJ_0209 写真に写っている景色は?

問題

解法
計算量はどんなに悪くても n^2 * m^2 * 4 = 10000 * 250 * 4 = 10000000 より少ないので、
全探索すれば大丈夫。正確な計算をすると、もっと小さくなる。

回転させた図形の作り方
 1、回転させる二次元配列(p[x][y])に、
   (下から上に一列とりpn[x][y]の空いている一番上の行に入れる)を左から右へ繰り返し、
   新しい二次元配列 pn[x][y] を作る。
 2、pn[x][y]に1を適用しさらに回転させた図形を作っていく。
これを繰り返せば、右に90度ずつ回転させた配列が得られる

コードのネストがなんかすごいことになってしまった。
実装

#include <cstdio>
#include <algorithm>

const int MAX_N = 100;
const int MAX_M = 50;

int N, M;
int pic[MAX_N][MAX_N];
int p[4][MAX_M][MAX_M];
int ansx, ansy;

//写真の切れ端をくるくる回す関数
void kurukuru(){
	for(int k = 1; k < 4; k++){
		int x = 0;
		for(int i = M - 1; i >= 0; i--){
			for(int j = 0; j < M; j++)
				p[k][x][j] = p[k - 1][j][i];
			x++;
		}
	}
}
bool c(int x, int y, int k){
	for(int j = 0; j < M; j++){
		for(int i = 0; i < M; i++){
			if(p[k][i][j] == -1) continue;
			if(p[k][i][j] != pic[x + i][y + j]){
				return false;
			}
		}
	}
	return true;
}
void solve(){
	for(int y = 0; y <= N - M; y++){
		for(int x = 0; x <= N - M; x++){
			//回転させた4種類の切れ端を順に試す
			for(int k = 0; k < 4; k++){
				if(c(x, y, k)){
					//ぴったり!
					for(int j = 0; j < M; j++){
						for(int i = 0; i < M; i++){
							if(p[k][i][j] != -1){
								ansx = i + x + 1;
								ansy = j + y + 1;
								return;
							}
						}
					}
				}
			}
		}
	}
	ansx = -1; ansy = -1;
}
int main(){
	while(scanf("%d %d", &N, &M) && N){
		for(int i = 0; i < N; i++)
			for(int j = 0; j < N; j++)
				scanf("%d", &pic[j][i]);
		for(int i = 0; i < M; i++)
			for(int j = 0; j < M; j++)
				scanf("%d", &p[0][j][i]);
		kurukuru();
		solve();
		if(ansx != -1)
			printf("%d %d\n", ansx, ansy);
		else
			printf("NA\n");
	}
	return 0;
}