[백준/BOJ] 백준 4577번 : 소코반

2021. 9. 3. 00:07알고리즘 문제풀이

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

 

4577번: 소코반

소코반은 1982년에 일본에서 만들어진 게임으로, 일본어로 창고지기라는 뜻이다. 이 게임은 캐릭터를 이용해 창고 안에 있는 박스를 모두 목표점으로 옮기는 게임이다. 목표점의 수와 박스의 수

www.acmicpc.net

움직일 위치와 박스가 움직일 위치들을 고려하여 문제를 해결했다.

 

코드

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

int r, c;
vector<string> board;
pair<int, int> here;
int dxdy[4][2] = { {0,-1},{-1,0},{0,1},{1,0} };
int game_cnt = 0;
string result;

void Pre()
{
	game_cnt++;
	board.clear();
}

bool Finish()
{
	for (int i = 0; i < r; i++)
	{
		for (int j = 0; j < c; j++)
		{
			//목표지점에 없는 박스가 있을때
			if (board[i][j] == 'b')
				return false;
		}
	}

	return true;
}

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

	while (1)
	{
		Pre();

		cin >> r >> c;

		if (r == 0 && c == 0)
			break;

		for (int i = 0; i < r; i++)
		{
			string input;
			cin >> input;

			board.push_back(input);

			for (int j = 0; j < c; j++)
			{
				if (board[i][j] == 'w' || board[i][j] == 'W')
				{
					here = make_pair(i, j);
				}
			}
		}

		string order;
		cin >> order;

		for (int i = 0; i < order.size(); i++)
		{
			pair<int, int> there;
			pair<int, int> there2;

			if (Finish() == true)
			{
				result = "complete";
				break;
			}

			if (order[i] == 'L')
			{
				there = make_pair(here.first + dxdy[0][0], here.second + dxdy[0][1]);
				there2 = make_pair(there.first + dxdy[0][0], there.second + dxdy[0][1]);
			}

			else if (order[i] == 'U')
			{
				there = make_pair(here.first + dxdy[1][0], here.second + dxdy[1][1]);
				there2 = make_pair(there.first + dxdy[1][0], there.second + dxdy[1][1]);
			}

			else if (order[i] == 'R')
			{
				there = make_pair(here.first + dxdy[2][0], here.second + dxdy[2][1]);
				there2 = make_pair(there.first + dxdy[2][0], there.second + dxdy[2][1]);
			}

			else if (order[i] == 'D')
			{
				there = make_pair(here.first + dxdy[3][0], here.second + dxdy[3][1]);
				there2 = make_pair(there.first + dxdy[3][0], there.second + dxdy[3][1]);
			}

			//there이 빈칸 또는 목표지점일때
			if (board[there.first][there.second] == '.' || board[there.first][there.second] == '+')
			{
				if (board[here.first][here.second] == 'w')
					board[here.first][here.second] = '.';
				else if (board[here.first][here.second] == 'W')
					board[here.first][here.second] = '+';

				if (board[there.first][there.second] == '.')
					board[there.first][there.second] = 'w';
				else if (board[there.first][there.second] == '+')
					board[there.first][there.second] = 'W';

				here = there;
			}

			//there칸에 박스가 있을때
			if (board[there.first][there.second] == 'b' || board[there.first][there.second] == 'B')
			{
				//박스가 옮겨지는 지점(there2)이 비어있을때
				if (board[there2.first][there2.second] == '.' || board[there2.first][there2.second] == '+')
				{
					if (board[there2.first][there2.second] == '.')
						board[there2.first][there2.second] = 'b';
					else if (board[there2.first][there2.second] == '+')
						board[there2.first][there2.second] = 'B';

					if (board[there.first][there.second] == 'b')
						board[there.first][there.second] = '.';
					else if (board[there.first][there.second] == 'B')
						board[there.first][there.second] = '+';

					if (board[here.first][here.second] == 'w')
						board[here.first][here.second] = '.';
					else if (board[here.first][here.second] == 'W')
						board[here.first][here.second] = '+';

					if (board[there.first][there.second] == '.')
						board[there.first][there.second] = 'w';
					else if (board[there.first][there.second] == '+')
						board[there.first][there.second] = 'W';

					here = there;
				}
			}

			if (i == order.size() - 1)
			{
				if (Finish() == true)
				{
					result = "complete";
					break;
				}

				else
				{
					result = "incomplete";
					break;
				}
			}
		}

		cout << "Game " << game_cnt << ": " << result << "\n";
		for (int i = 0; i < r; i++)
		{
			cout << board[i] << "\n";
		}
	}

	return 0;
}