Post

Baekjoon1600-말이 되고픈 원숭이

백준 사이트 1600 - 말이 되고픈 원숭이 문제입니다.

1. 문제

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


2. Input , Output


3. 분류 및 난이도

BFS문제입니다.
백준에서는 Gold5의 난이도를 책정하고 있습니다.


4. 생각한 것들

  • 골드5 치고는 어려운 것 같습니다. 생각할 거리가 생각보다 많기 때문입니다. 구현 자체는 쉬운 편.
  • 주의 해야할 점이 입력이 가로의 길이, 세로의 길이로 4와 5를 입력받으면
    1
    2
    3
    4
    5
    6
    
    4 5
    0 0 0 0 
    0 0 0 0 
    0 0 0 0 
    0 0 0 0 
    0 0 0 0 
    

    이렇게 배열이 생긴다는 것에 주의해야합니다.

  • DP로 풀어야겠다고 생각했습니다.
    • 최소 이동 횟수 문제가아닌 모든 경우의 수 문제인줄 알고 DP로 풀려했는데 아닌걸 보고 DP코드를 지웠습니다.
  • 일반적인 BFS와 다르게 방문처리릍 특별하게 해줘야합니다.
    • 다음 인풋을 예시로 들면
      1
      2
      3
      4
      5
      6
      
        1
        5 4 
        0 0 0 0 0
        0 0 0 0 0
        0 0 0 1 1
        0 0 0 1 0
      

      결과는 이렇게 되어야 합니다.

      1
      2
      3
      4
      
        0 1 0 0 0
        0 2 3 4 0
        0 0 0 x x
        0 0 0 x 5
      

      말처럼 바로 움직여버리면 움직임을 다 소비해버려 다음과 같이 이동할 수가 없습니다.

      1
      2
      3
      4
      
        0 0 0 0 0
        0 1 2 3 0
        0 0 0 x x
        0 0 0 x -1
      

      그래서 말의 이동횟수에 대한 카운트를 잘 세줘야합니다.
      방문 처리를 미리 해버리면 방문하였기에 접근을 안하고, 방문 처리를 안해버리면 모든 배열을 돌아야하므로 시간초과가 날 것 입니다.

  • 해결법은 방문처리 배열의 차원을 하나 더 두는 것입니다.
  • 차원을 하나 더 두었기에 말처럼 이동했을 때 방문처리와 원숭이로 이동했을 때 방문처리를 관리할 수 있습니다.

5. code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;

const int MAX = 201;
int MAP[MAX][MAX] = { 0, };
bool v[MAX][MAX][32] = { false, };
int W, H, K;

int dx[4] = { -1,0,1,0 };
int dy[4] = { 0,1,0,-1 };
int horsex[8] = { -1,-2,-2,-1,1,2, 2, 1 };
int horsey[8] = { -2,-1, 1, 2,2,1,-1,-2 };

void Input()
{
	cin >> K;
	cin >> W >> H;
	for (int i = 0; i < H; ++i)
	{
		for (int j = 0; j <W; ++j)
			cin >> MAP[i][j];
	}
}

int Solve()
{
	//BFS
	//좌표 값, k 카운트 값, 이동횟수
	memset(v, false, sizeof(v));
	queue < pair<pair<int, int>, pair<int,int>>> q;

	q.push(make_pair(make_pair(0, 0), make_pair(0,0)));
	v[0][0][0] = true;
	while (!q.empty())
	{
		int x = q.front().first.first;
		int y = q.front().first.second;
		int horse = q.front().second.first;
		int result = q.front().second.second;
		//cout << "x : " << x << "y : " << y << "horse" <<horse<<"result : "<<result<< '\n';
		if (x == (H - 1) && y == (W - 1))
			return result;
		q.pop();
		//말처럼 뛰기
		if (horse < K)
		{
			for (int k = 0; k < 8; ++k)
			{
				int newX = x + horsex[k];
				int newY = y + horsey[k];
				//cout << newX << " " << newY << '\n';
				if (0 <= newX && newX < H && 0 <= newY && newY < W && v[newX][newY][horse+1] == false && MAP[newX][newY] !=1)
				{
					q.push(make_pair(make_pair(newX, newY),make_pair(horse+1, result+1)));
					v[newX][newY][horse+1] = true;
				}
			}
		}
		//말처럼 안뛰기
		for (int k = 0; k < 4; ++k)
		{
			int newX = x + dx[k];
			int newY = y + dy[k];

			if (0 <= newX && newX < H && 0 <= newY && newY < W && v[newX][newY][horse] == false && MAP[newX][newY] != 1)
			{
				q.push(make_pair(make_pair(newX, newY), make_pair(horse, result + 1)));
				v[newX][newY][horse] = true;
			}
		}
	}
	return -1;
}


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

	Input();
	cout<<Solve();
	
	
	return 0;
}

6. 후기

3차원 배열 == 어렵습니다.

This post is licensed under CC BY 4.0 by the author.