문제 설명
현대모비스에서 개발한 실내공조 제어 시스템은 차내에 승객이 탑승 중일 때 항상 쾌적한 실내온도(t1 ~ t21)를 유지할 수 있도록 합니다. 현재(0분) 실내온도는 실외온도와 같습니다.
실내공조 제어 시스템은 실내온도를 조절하기 위해 에어컨의 전원을 켜 희망온도를 설정합니다. 희망온도는 에어컨의 전원이 켜져 있는 동안 원하는 값으로 변경할 수 있습니다. 실내온도와 희망온도가 다르다면 1분 뒤 실내온도가 희망온도와 같아지는 방향으로 1도 상승 또는 하강합니다. 실내온도가 희망온도와 같다면 에어컨이 켜져 있는 동안은 실내온도가 변하지 않습니다.
에어컨의 전원을 끄면 실내온도가 실외온도와 같아지는 방향으로 매 분 1도 상승 또는 하강합니다. 실내온도와 실외온도가 같다면 실내온도는 변하지 않습니다.
에어컨의 소비전력은 현재 실내온도에 따라 달라집니다. 에어컨의 희망온도와 실내온도가 다르다면 매 분 전력을 a만큼 소비하고, 희망온도와 실내온도가 같다면 매 분 전력을 b만큼 소비합니다. 에어컨이 꺼져 있다면 전력을 소비하지 않으며, 에어컨을 켜고 끄는데 필요한 시간과 전력은 0이라고 가정합니다.
실내공조 제어 시스템은 차내에 승객이 탑승 중일 때 실내온도를 t1 ~ t2도 사이로 유지하면서, 에어컨의 소비전력을 최소화합니다.
다음은 실외온도가 28도, t1= 18, t2 = 26, a = 10 b = 8인 예시입니다.
시간(분) | 승객 탑승 |
0 | x |
1 | x |
2 | o |
3 | o |
4 | o |
5 | o |
6 | o |
- 승객이 탑승 중인 2 ~ 6분의 실내온도를 18 ~ 26도 사이로 유지해야 합니다.
다음은 2 ~ 6분의 실내온도를 쾌적한 온도로 유지하는 방법 중 하나입니다.
시간(분) | 승객 탑승 | 실내온도 | 희망온도 |
0 | x | 28 | 26 |
1 | x | 27 | 26 |
2 | o | 26 | 26 |
3 | o | 26 | 26 |
4 | o | 26 | 26 |
5 | o | 26 | 26 |
6 | o | 26 | off |
- 0분의 실내온도는 항상 실외온도와 같습니다.
- 6분에 에어컨의 전원을 껐습니다.
0 ~ 5분에 에어컨의 희망온도를 26도로 설정했습니다. 0 ~ 1분에 희망온도와 실내온도가 다르므로 전력을 매 분 10씩, 2 ~ 5분에 희망온도와 실내온도가 같으므로 전력을 매 분 8씩 소비했습니다. 이때 총 소비전력은 52(= 2 × 10 + 4 × 8)입니다.
다음은 2 ~ 6분의 실내온도를 쾌적한 온도로 유지하는 또 다른 방법입니다.
시간(분) | 승객 탑승 | 실내온도 | 희망온도 |
0 | x | 28 | 24 |
1 | x | 27 | 24 |
2 | o | 26 | 24 |
3 | o | 25 | 24 |
4 | o | 24 | off |
5 | o | 25 | off |
6 | o | 26 | off |
0 ~ 3분에 에어컨의 희망온도를 24도로 설정해 전력을 매 분 10씩 소비했습니다. 이때 총 소비전력은 40(= 4 × 10)이며, 이보다 소비전력이 적어지는 방법은 없습니다.
실외온도를 나타내는 정수 temperature, 쾌적한 실내온도의 범위를 나타내는 정수 t1, t2, 에어컨의 소비전력을 나타내는 정수 a, b와 승객이 탑승 중인 시간을 나타내는 1차원 정수 배열 onboard가 매개변수로 주어집니다. 승객이 탑승 중인 시간에 쾌적한 실내온도를 유지하기 위한 최소 소비전력을 return 하도록 solution 함수를 완성해 주세요.
https://school.programmers.co.kr/learn/courses/30/lessons/214289
제한 사항
- -10 ≤ temperature ≤ 40
- -10 ≤ t1 < t2 ≤ 40
- temperature는 t1 ~ t2 범위 밖의 값입니다.
- 1 ≤ a, b ≤ 100
- a는 에어컨의 희망온도와 실내온도가 다를 때의 1분당 소비전력을 나타냅니다.
- b는 에어컨의 희망온도와 실내온도가 같을 때의 1분당 소비전력을 나타냅니다.
- 2 ≤ onboard의 길이 ≤ 1,000
- onboard[i]는 0 혹은 1이며, onboard[i]가 1이라면 i분에 승객이 탑승 중이라는 것을 의미합니다.
- onboard[0] = 0
- onboard에 1이 최소 한 번 이상 등장합니다.
- 승객이 탑승 중인 시간에 쾌적한 실내온도를 유지하는 것이 불가능한 경우는 주어지지 않습니다.
풀이
문제조차 이해하기 힘든 문제였다.
문제를 풀기 위해서는 문제를 단순화할 필요가 있다.
a분에 b온도를 맞추는 경우는 총 세 가지이다.
- i-1분에 온도가 j-1이었을 경우
- i-1분에 온도가 j이었을 경우
- i-1분에 온도가 j+1이었을 경우
에어컨이 꺼졌을 때 실외온도에 따라 온도가 변하기 때문에 주의해야 한다.
기본적으로 반복문을 진행하면서 i분에서 j온도가 되었다고 가정하면서 i+1분에 진행될 수 있는 경우를 갱신해 준다.
현재 온도와 외부 온도에 따라 총 6가지의 경우의 수가 생긴다.
- 현재 온도 < 외부 온도, j → j-1로 변화
- 현재 온도 > 외부 온도, j → j-1로 변화
- 현재 온도 = 외부 온도, j → j로 변화
- 현재 온도 != 외부 온도, j → j로 변화
- 현재 온도 < 외부 온도, j → j+1로 변화
- 현재 온도 > 외부 온도, j → j+1로 변화
즉, 정리하자면 현재 i분에 j온도라고 가정하면, { i+1, j-1 }, { i+1, j }, { i+1, j+1 }를 갱신해야 한다.
이때, 현재 온도와 외부 온도에 따라 값을 갱신하면 된다.
에어컨을 켤 필요가 없다면 0, 온도를 변화시킨다면 a, 온도를 유지시킨다면 b를 더하면 된다.
energy[i+1][j-1] = min(energy[i+1][j-1], energy[i][j] + (temperature < j ? 0 : a));
energy[i+1][j] = min(energy[i+1][j], energy[i][j] + (temperature == j ? 0 : b));
energy[i+1][j+1] = min(energy[i+1][j+1], energy[i][j] + (temperature > j ? 0 : a));
이때, onboard[i]가 1이라면 항상 t1~t2의 온도 사이에 있어야 하기 때문에 조건에 맞지 않는 경우는 넘기면 된다.
또한, 실외온도의 최솟값이 -10이다.
이를 간단하게 만들기 위해 모든 온도에 10을 더해 준다.
전체 코드
#include <string>
#include <vector>
#include <iostream>
using namespace std;
int solution(int temperature, int t1, int t2, int a, int b, vector<int> onboard) {
int answer = 0;
const int MAX = 999'999'999;
//음수 처리
temperature += 10;
t1 += 10;
t2 += 10;
vector<vector<int>> energy(onboard.size()+1, vector<int>(51, MAX));
energy[0][temperature] = 0;
//시간 진행
for(int i = 0; i < onboard.size(); i++)
{
for(int j = 0; j <= 50; j++)
{
//onboard가 1이면 t1~t2사이: 아니라면 제외
if (onboard[i] == 1 && (j < t1 || j > t2)) continue;
//갱신되지 않은 경우 제외(진행될 수 없는 경우)
if(energy[i][j] >= MAX) continue;
energy[i+1][j-1] = min(energy[i+1][j-1], energy[i][j] + (temperature < j ? 0 : a));
energy[i+1][j] = min(energy[i+1][j], energy[i][j] + (temperature == j ? 0 : b));
energy[i+1][j+1] = min(energy[i+1][j+1], energy[i][j] + (temperature > j ? 0 : a));
}
}
answer = MAX;
for (int j = 0; j <= 50; j++)
{
answer = min(answer, energy[onboard.size()][j]);
}
return answer;
}