1 분 소요

경주로건설 (프로그래머스 Level 3)

https://school.programmers.co.kr/learn/courses/30/lessons/67259

일반적인 BFS 처럼 보였지만 ‘도로 개수’에 조금 애를 먹은 문제이다
처음에는 일일이 cost를 계산하다가
나중에는 ‘직선 개수’와 ‘코너 개수’를 계산하여 풀었다
(마지막에 직선 개수 -1 하여 계산)

세부적인 구현에 시간을 크게 쓴 점은 있지만
그래도 혼자의 힘으로 풀 수 있어 괜찮았다
(dp를 사용하는 김에 차라리 dfs로 푸는 쪽이 더 깔끔했을 수 있겠다 싶었다)

Code

#include <vector>
#include<queue>
#include<limits.h>

using namespace std;

enum dir
{
	down = 0,
	right,
	up,
	left,
};

int solution(vector<vector<int>> board) {
	const int n = board.size() - 1;
	int answer = 0;
	struct wayInfo
	{
		int y = 0;
		int x = 0;

		dir d = down;

		int f = 1;
		int c = 0;
	};

	queue<wayInfo> q;
	q.push(wayInfo());
	q.push({ 0,0,right });

	vector<vector<pair<int, int>>> dp1(n + 1, vector<pair<int, int>>(n + 1, { INT_MAX / 10 ,INT_MAX / 10 })); // up, down 상황일때 비교
	vector<vector<pair<int, int>>> dp2(dp1);   // left, right 상황일때 비교

	while (q.empty() == false)
	{
		wayInfo now = q.front();
		q.pop();
		int size = q.size();

		if (now.x < 0 || now.x > n ||
			now.y < 0 || now.y > n)
			continue;

		if (board[now.y][now.x] == 1)
			continue;

		if (now.d == up || now.d == down)
		{
			int cost = now.f + now.c * 5;
			int dCost = dp1[now.y][now.x].first + dp1[now.y][now.x].second * 5;
			if (cost >= dCost)
				continue;

			dp1[now.y][now.x] = {now.f,now.c};
		}
		else
		{
			int cost = now.f + now.c * 5;
			int dCost = dp2[now.y][now.x].first + dp2[now.y][now.x].second * 5;
			if (cost >= dCost)
				continue;

			dp2[now.y][now.x] = { now.f,now.c };
		}

		if (now.x == n &&
			now.y == n)
		{
			continue;
		}

		// 직진, 좌회전, 우회전
		for (int i = 0; i < 3; i++)
		{
			int nextDir = now.d;
			int nextF = now.f + 1;
			int nextC = now.c;

			if (i == 1)
			{
				nextDir--;
				if (nextDir < 0)
					nextDir = left;

				nextC++;
			}

			if (i == 2)
			{
				nextDir++;
				if (nextDir > left)
					nextDir = down;

				nextC++;
			}

			int nextX = now.x;
			int nextY = now.y;

			switch (nextDir)
			{
			case down:
				nextY++;
				break;
			case right:
				nextX++;
				break;
			case up:
				nextY--;
				break;
			case left:
				nextX--;
				break;
			}

			q.push(wayInfo{ nextY,nextX,static_cast<dir>(nextDir),nextF,nextC });
		}

	}

	answer = min(dp1[n][n].first + dp1[n][n].second * 5 - 1, dp2[n][n].first + dp2[n][n].second * 5 - 1);
	answer *= 100;

	return answer;
}

댓글남기기