[백준/BOJ] 백준 1600번 : 말이 되고픈 원숭이

2020. 8. 14. 00:22알고리즘 문제풀이

https://www.acmicpc.net/problem/1600

 

1600번: 말이 되고픈 원숭이

첫째 줄에 정수 K가 주어진다. 둘째 줄에 격자판의 가로길이 W, 세로길이 H가 주어진다. 그 다음 H줄에 걸쳐 W개의 숫자가 주어지는데, 0은 아무것도 없는 평지, 1은 장애물을 뜻한다. 장애물이 있��

www.acmicpc.net

현재 위치에서 말처럼 움직일 수 있는 횟수가 남았으면 말처럼 움직일 수 있는 방법과, 인접한 칸으로 움직일 수 있는 방법이 있고, 말처럼 움직일 수 있는 횟수가 없으면 인접한 칸으로 움직일 수 있는 방법뿐이다.

 

코드

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <utility>
using namespace std;

int w, h;
int dx_dy1[4][2] = { {0,-1},{-1,0},{0,1},{1,0} };
int dx_dy2[8][2] = { {-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2} };
int board[200][200];
int discoverd[200][200][31];
int depth[200][200][31];

void pre()
{
	for (int i = 0; i < 200; i++)
		for (int j = 0; j < 200; j++)
			for (int k = 0; k < 31; k++)
				discoverd[i][j][k] = 0;
}

//start는 시작지점과 k의 정보를 가지고 있다
int Solve(pair<pair<int, int>, int> start)
{
	pre();

	discoverd[start.first.first][start.first.second][start.second] = 1;
	depth[start.first.first][start.first.second][start.second] = 0;

	queue<pair<pair<int, int>, int>> q;
	q.push(start);

	while (!q.empty())
	{
		pair<pair<int, int>, int> here = q.front();
		q.pop();

		//맨 오른쪽 아래에 도착했을때
		if (here.first.first == h - 1 && here.first.second == w - 1)
			return depth[here.first.first][here.first.second][here.second];

		//말 처럼 움직일수 있는 횟수가 남았을때
		if (here.second > 0)
		{
			for (int i = 0; i < 8; i++)
			{
				pair<pair<int, int>, int> there = make_pair(make_pair(here.first.first + dx_dy2[i][0], here.first.second + dx_dy2[i][1]), here.second - 1);

				if (there.first.first >= 0 && there.first.first < h && there.first.second >= 0 && there.first.second < w && board[there.first.first][there.first.second] == 0 && discoverd[there.first.first][there.first.second][there.second] == 0)
				{
					discoverd[there.first.first][there.first.second][there.second] = 1;
					depth[there.first.first][there.first.second][there.second] = depth[here.first.first][here.first.second][here.second] + 1;
					q.push(there);
				}

			}
		}

		//인접한칸으로 움직을때
		for (int i = 0; i < 4; i++)
		{
			pair<pair<int, int>, int> there = make_pair(make_pair(here.first.first + dx_dy1[i][0], here.first.second + dx_dy1[i][1]), here.second);

			if (there.first.first >= 0 && there.first.first < h && there.first.second >= 0 && there.first.second < w && board[there.first.first][there.first.second] == 0 && discoverd[there.first.first][there.first.second][there.second] == 0)
			{
				discoverd[there.first.first][there.first.second][there.second] = 1;
				depth[there.first.first][there.first.second][there.second] = depth[here.first.first][here.first.second][here.second] + 1;
				q.push(there);
			}
		}
	}

	//맨 오른쪽 아래에 도착할 수 없을때
	return -1;
}

int main()
{
	cin.tie(NULL);
	ios_base::sync_with_stdio(false);

	int k;
	int temp;

	cin >> k;
	cin >> w >> h;

	for (int i = 0; i < h; i++)
		for (int j = 0; j < w; j++)
		{
			cin >> temp;
			board[i][j] = temp;
		}

	pair<pair<int, int>, int> start = make_pair(make_pair(0, 0), k);

	cout << Solve(start);

	return 0;
}