알고리즘 문제/프로그래머스

에어컨 [Lv. 3] (C++)

우대비 2024. 6. 29. 11:48
반응형
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

승객이 차량에 탑승 중일 때 항상 쾌적한 실내온도 (t1 ~ t2)를 유지 해야합니다.

항상 에어컨을 틀어놓는 것도 방법이 될 수 있지만 전기세를 아껴야 하기에

에어컨을 트는 최적의 방법을 찾아야 합니다.

따라서 우리는 승객이 탑승 중일 때 쾌적한 실내온도를 유지하는 방법 중 가장 적은 전기 사용량을 찾아야 합니다.

 

풀이 방법

경우의 수는 총 3개가 있습니다.

에어컨으로 온도를 낮추는 경우와 온도를 유지하는 경우, 그리고 에어컨을 끄는 경우

이 3개의 경우를 모두 탐색하여 최적의 전기 사용량을 찾으면 됩니다.

void dfs(vector<int>& onboard, int idx, int curTmpt, int cost)
{
	// 종료 후 비용 비교
    if (idx == onboard.size())
    {
        answer = min(answer, cost);
        return;
    }
    
    // 쾌적한 온도가 아니라면 return
    if (onboard[idx] == 1  && (curTmpt < _t1 || curTmpt > _t2))
        return;
    
    // 에어컨 끄기
        dfs(onboard, idx + 1, min(initTmpt, curTmpt + 1), cost);
    // 에어컨 유지
        dfs(onboard, idx + 1, curTmpt, cost + _b);
    // 에어컨 켜기'
        dfs(onboard, idx + 1, curTmpt - 1, cost + _a);
}

그럼 위처럼 dfs를 만들 수 있게 됩니다.

위의 코드로도 정답을 찾을 수는 있지만 속도 문제에 의해 해결은 안됩니다.

이 문제를 해결하기 위해서는 dynamic programming을 접목시킬 필요가 있습니다.

 

(5분에 21도)에 도달하기 위한 여러 경로가 있고 지금 모든 경로를 탐색중이라고 할 때

이미 최적의 경로가 나온 상황이라면 이후의 경로들은 탐색하지 않아도 상관없습니다.

( 우리는 경로를 탐색하는게 목적이 아니라 비용을 구하고 있기 때문,

  어차피 같은 위치에 같은 온도라면 이후의 경우의 수도 100% 동일하기에 중복 탐색하게 됨)

그렇기에 중간에 데이터를 저장하는 코드를 넣어주었습니다.

 

vector<vector<int>> dp(1001, vector<int>(51, 100000000));

if (dp[idx][curTmpt] <= cost )
    return;
dp[idx][curTmpt] = cost ;

최적의 경로를 찾은 상황이 아니라면 탐색 종료

 

 

 

위의 설명에는 경우의 수가 3개라고 이야기 했지만 사실 하나 더 있습니다.

실내 온도가 쾌적 온도 범위보다 낮을 때 [온도를 올리는 경우]입니다.

initTmpt = temperature ;
_t1 = t1 ;
_t2 = t2;
_a = a;
_b = b;

if (initTmpt < _t1)
    initTmpt = _t2 + (_t1 - initTmpt);

이 부분은 실외 온도를 쾌적 온도 범위보다 높게 바꿔주어 계산할 필요가 없게 했습니다.

구하는 것은 전기 소비량이기 때문에 상관없습니다.

 

전체 코드

#include <string>
#include <vector>
#include <iostream>

using namespace std;

vector<vector<int>> dp(1001, vector<int>(51, 100000000));
int initTmpt, _t1, _t2, _a, _b, answer = 10000000;

void dfs(vector<int>& onboard, int idx, int curTmpt, int cost)
{
    if (idx == onboard.size())
    {
        answer = min(answer, cost);
        return;
    }
    
    if (onboard[idx] == 1  && (curTmpt < _t1 || curTmpt > _t2))
        return;
    
    if (dp[idx][curTmpt] <= cost )
        return;

    dp[idx][curTmpt] = cost ;
    
    // 에어컨 끄기
        dfs(onboard, idx + 1, min(initTmpt, curTmpt + 1), cost);
    // 에어컨 유지
        dfs(onboard, idx + 1, curTmpt, cost + _b);
    // 에어컨 켜기'
        dfs(onboard, idx + 1, curTmpt - 1, cost + _a);
}

int solution(int temperature, int t1, int t2, int a, int b, vector<int> onboard) {
    initTmpt = temperature ;
    _t1 = t1 ;
    _t2 = t2;
    _a = a;
    _b = b;
    
    if (initTmpt < _t1)
        initTmpt = _t2 + (_t1 - initTmpt);
    
    dfs(onboard, 0, initTmpt, 0);

    return answer;
}
반응형
LIST

'알고리즘 문제 > 프로그래머스' 카테고리의 다른 글

퍼즐 조각 채우기 [Lv. 3] (C++)  (1) 2024.06.30
n + 1 카드 게임 [Lv. 3] (C++)  (1) 2024.06.30
수레 움직이기 [Lv. 3] (C++)  (0) 2024.06.28
여행경로 [Lv. 3] (C++)  (0) 2024.06.28
가장 먼 노드 [Lv. 3]  (0) 2024.06.28