알고리즘 :: 백준 :: 시뮬레이션 :: 1103:: 게임

Embedded June·2021년 8월 4일
0

알고리즘::백준

목록 보기
106/109

1. 문제 분석하기

1.1. 문제 의도

  • 시뮬레이션 문제입니다.

1.2. 문제 조건

  1. 동전은 가장 왼족 위 (0, 0)에 있다.
  2. 동전이 있는 칸의 숫자만큼 상, 하, 좌, 우 중 한 방향으로 이동한다.
    (이때, 중간에 지나치는 구멍은 무시한다.)
  3. 구멍에 빠지거나 보드 바깥으로 나간다면 게임은 종료한다.
  4. 무한번 움직일 수 있다면 -1을 출력한다.

2. 문제 해결하기

  • 이 문제의 핵심 아이디어는 상, 하, 좌, 우를 이동했을 때 가장 오래 게임을 할 수 있는 경우를 선택하는 것입니다.
    • 즉, 현재 동전이 있는 칸을 (cy, cx)라고 할 때,
      다음 동전이 이동할 칸을 (ny, nx)라고 한다면,
    • (cy, cx)의 최대 게임 횟수는 4방향에 대한 게임 횟수들 중 최대값을 저장합니다.
    • 이때 (ny, nx)가 구멍에 빠지거나, 범위를 초과한다면 바로 프로그램 종료합니다.
  • 따라서 이 문제는 DP가 결합된 시뮬레이션 문제입니다.
  • 동전이 무한번 움직이는 경우는 cycle이 생성되는 경우입니다. 방문표시를 한 곳에 다시 왔다면 cycle이 발생한 것이니 프로그램을 종료합니다.

3. 코드

#include <iostream>
#include <cstdlib>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#define MAX 50
using namespace std;

int N, M, dp[MAX][MAX];
char map[MAX][MAX];
bool visited[MAX][MAX];
int d[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};

bool checkRange(int cy, int cx) {
	return (0 <= cy && cy < N) && (0 <= cx && cx < M);
} 

int solve(int cy, int cx) {
	if (visited[cy][cx]) { cout << -1; exit(0); }
	if (dp[cy][cx]) return dp[cy][cx];
	
	int weight = map[cy][cx] - '0';
	visited[cy][cx] = true;
	for (int i = 0; i < 4; ++i) {
		int ny = cy + weight * d[i][0], nx = cx + weight * d[i][1];
		if (!checkRange(ny, nx) || map[ny][nx] == 'H') continue;
		dp[cy][cx] = max(dp[cy][cx], solve(ny, nx) + 1);
	}
	visited[cy][cx] = false;
	return dp[cy][cx];
}
int main() {
    ios::sync_with_stdio(false), cin.tie(NULL);
    cin >> N >> M;
    for (int i = 0; i < N; ++i) cin >> map[i];
    cout << solve(0, 0) + 1;
}

4. 결과

profile
임베디드 시스템 공학자를 지망하는 컴퓨터공학+전자공학 복수전공 학부생입니다. 타인의 피드백을 수용하고 숙고하고 대응하며 자극과 반응 사이의 간격을 늘리며 스스로 반응을 컨트롤 할 수 있는 주도적인 사람이 되는 것이 저의 20대의 목표입니다.

0개의 댓글