
🦈1. Struct 만들기struct SHARK 정의
struct SHARK {
    int y, x;
    int dir;
    int p[5][4];
    bool alive = true;
};
vector<SHARK> shark;struct MAP_INFO 정의
struct MAP_INFO {
    vector<int> v;
    int scent_time=0;
    int scent_host=0;
};
MAP_INFO map[MAX][MAX];🦈2. Input Data	//input shark position & scent
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			int n;  cin >> n; 
			if (n != 0) {
				map[i][j].v.push_back(n);
				shark[n].y = i;
				shark[n].x = j;
			}
			map[i][j].scent_host = 0;
			map[i][j].scent_time = 0;
		}
	}	//input shark direction
	for (int i = 1; i <= M; i++) {
		int dir; 
		cin >> dir;
		shark[i].dir = dir;
	}	//input shark's priority direction
	for (int i = 1; i <= M; i++) {
		for (int dir = 1; dir <= 4; dir++) {
			int a, b, c, d;
			cin >> a >> b >> c >> d;
			shark[i].p[dir][0] = a;
			shark[i].p[dir][1] = b;
			shark[i].p[dir][2] = c;
			shark[i].p[dir][3] = d;
		}
	}🦈3. Setting Smelltime은 게임이 시작되고 흐른 시간을 나타내며 scent_time은 현재 시간 (time)을 기준으로 k초 후까지만 유효하다//time=current time
void setting_smell(int time) {
	for (int i = 1; i <= M; i++) {
		if (shark[i].alive == false) continue;
		int y = shark[i].y;
		int x = shark[i].x;
		//현재 시간을 기준으로 k초 후 까지만 유효함
		map[y][x].scent_time = time + K; 
		map[y][x].scent_host = i;
	}
}🦈4. Move Shark	for (int i = 1; i <= M; i++) {
		if (shark[i].alive == false) continue;
		int y = shark[i].y;
		int x = shark[i].x;
		map[y][x].v.clear();
	}if (map[ny][nx].scent_time<= time) : 이동할 곳의 냄새의 시간이 현재 시간 time과 같거나 작다는 뜻은 이동 했을 때 해당 칸의 냄새는 사라진다는 의미이고 따라서 해당 칸은 빈 칸이 된다는 뜻이다bool flag 변수를 두어 인접한 아무 냄새가 없는 칸을 찾았을 경우에는 true로 바꾸어 준다 (자신의 냄새가 있는 칸으로 이동하지 않아도 된다는 의미로)	/*
	2. 움직이려는 칸에 아무 냄새가 없는 경우, 
	자신의 냄새가 있는 경우를 동시에 조사하고 
	빈칸에 넣지 못했을 경우 자신의 냄새가 있는 칸에 넣어줌
	*/
	for (int i = 1; i <= M; i++) {
		if (shark[i].alive == false) continue;
		int y = shark[i].y;
		int x = shark[i].x;
		int dir = shark[i].dir;
		int tmpX, tmpY, tmpD;
		tmpX = tmpY = tmpD = -1;
		bool flag = false;
		for (int d = 0; d < 4; d++) {
			//현재 방향 dir을 기준으로 d번째 우선 순위
			int nDir = shark[i].p[dir][d]; 
			int ny = y + dy[nDir];
			int nx = x + dx[nDir];
			if (ny <1 || nx < 1 || ny >N || nx > N) continue;
			
			//scnet_time이 현재시간보다 작거나 같다는 뜻은 비었다는 뜻
			if (map[ny][nx].scent_time<= time) {
				flag = true;
				map[ny][nx].v.push_back(i);
				shark[i].y = ny;
				shark[i].x = nx;
				shark[i].dir = nDir;
				break;
			}
			else {
				//우선 순위가 높은 순으로 조사했을 때 자기 칸
				if (map[ny][nx].scent_host == i) {
					//자기보다 우선순위가 높은 방향에서 자기 칸을 아직 못 찾았을 경우
					if (tmpX == -1) {
						tmpY = ny;
						tmpX = nx;
						tmpD = nDir;
					}
				}
			}
		}
		if (flag==false) {
			map[tmpY][tmpX].v.push_back(i);
			shark[i].y = tmpY;
			shark[i].x = tmpX;
			shark[i].dir = tmpD;
		}
	}🦈5. Killing Shark		if (map[y][x].v.size() >= 2) {
			sort(map[y][x].v.begin(), map[y][x].v.end());
			int small = map[y][x].v[0];
			for (int i = 1; i < map[y][x].v.size(); i++) {
				int idx = map[y][x].v[i];
				shark[idx].alive = false;
			}
			map[y][x].v.clear();
			map[y][x].v.push_back(small);
			map[y][x].scent_host = small;
		}Source Code#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX = 21;
int N, M, K;
int dy[] = {0, -1, 1, 0 ,0};
int dx[] = {0, 0,0, -1, 1};
struct SHARK {
	int y, x;
	int dir;
	int p[5][4];
	bool alive = true;
};
vector<SHARK> shark;
struct MAP_INFO {
	vector<int> v;
	int scent_time=0;
	int scent_host=0;
};
MAP_INFO map[MAX][MAX];
//time=current time
void setting_smell(int time) {
	for (int i = 1; i <= M; i++) {
		if (shark[i].alive == false) continue;
		int y = shark[i].y;
		int x = shark[i].x;
		//현재 시간을 기준으로 k초 후 까지만 유효함
		map[y][x].scent_time = time + K; 
		map[y][x].scent_host = i;
	}
}
void move_shark(int time) {
	//1. 맵의 각 칸에 있는 상어를 비워줌
	for (int i = 1; i <= M; i++) {
		if (shark[i].alive == false) continue;
		int y = shark[i].y;
		int x = shark[i].x;
		map[y][x].v.clear();
	}
	/*
	2. 움직이려는 칸에 아무 냄새가 없는 경우, 
	자신의 냄새가 있는 경우를 동시에 조사하고 
	빈칸에 넣지 못했을 경우 자신의 냄새가 있는 칸에 넣어줌
	*/
	for (int i = 1; i <= M; i++) {
		if (shark[i].alive == false) continue;
		int y = shark[i].y;
		int x = shark[i].x;
		int dir = shark[i].dir;
		int tmpX, tmpY, tmpD;
		tmpX = tmpY = tmpD = -1;
		bool flag = false;
		for (int d = 0; d < 4; d++) {
			//현재 방향 dir을 기준으로 d번째 우선 순위
			int nDir = shark[i].p[dir][d]; 
			int ny = y + dy[nDir];
			int nx = x + dx[nDir];
			if (ny <1 || nx < 1 || ny >N || nx > N) continue;
			
			//scnet_time이 현재시간보다 작거나 같다는 뜻은 비었다는 뜻
			if (map[ny][nx].scent_time<= time) {
				flag = true;
				map[ny][nx].v.push_back(i);
				shark[i].y = ny;
				shark[i].x = nx;
				shark[i].dir = nDir;
				break;
			}
			else {
				//우선 순위가 높은 순으로 조사했을 때 자기 칸
				if (map[ny][nx].scent_host == i) {
					//자기보다 우선순위가 높은 방향에서 자기 칸을 아직 못 찾았을 경우
					if (tmpX == -1) {
						tmpY = ny;
						tmpX = nx;
						tmpD = nDir;
					}
				}
			}
		}
		if (flag==false) {
			map[tmpY][tmpX].v.push_back(i);
			shark[i].y = tmpY;
			shark[i].x = tmpX;
			shark[i].dir = tmpD;
		}
	}
}
void killing_shark(int time) {
	for (int i = 1; i <= M; i++) {
		if (shark[i].alive == false) continue;
		int y = shark[i].y;
		int x = shark[i].x;
		//한 칸에 상어 두 마리 이상인 경우 작은 상어만 살아 남음
		if (map[y][x].v.size() >= 2) {
			sort(map[y][x].v.begin(), map[y][x].v.end());
			int small = map[y][x].v[0];
			for (int i = 1; i < map[y][x].v.size(); i++) {
				int idx = map[y][x].v[i];
				shark[idx].alive = false;
			}
			map[y][x].v.clear();
			map[y][x].v.push_back(small);
			map[y][x].scent_host = small;
		}
	}
}
void input() {
	cin >> N >> M >> K;
	shark = vector<SHARK>(M+1);
	//input shark position & scent
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			int n;  cin >> n; 
			if (n != 0) {
				map[i][j].v.push_back(n);
				shark[n].y = i;
				shark[n].x = j;
			}
			map[i][j].scent_host = 0;
			map[i][j].scent_time = 0;
		}
	}
	//input shark direction
	for (int i = 1; i <= M; i++) {
		int dir; 
		cin >> dir;
		shark[i].dir = dir;
	}
	//input shark's priority direction
	for (int i = 1; i <= M; i++) {
		for (int dir = 1; dir <= 4; dir++) {
			int a, b, c, d;
			cin >> a >> b >> c >> d;
			shark[i].p[dir][0] = a;
			shark[i].p[dir][1] = b;
			shark[i].p[dir][2] = c;
			shark[i].p[dir][3] = d;
		}
	}
}
bool check_vaild() {
	for (int i = 2; i <= M; i++) 
		if (shark[i].alive == true) return false;
	return true;
}
int solution() {
	int answer = -1;
	for (int time = 0; time < 1001; time++) {
		if (check_vaild()) {
			answer = time;
			break;
		}
		setting_smell(time);
		move_shark(time);
		killing_shark(time);
	}
	return answer;
}
int main() {
	input();
	cout<<solution()<<endl;
	return 0;
}