Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- spread 연산자
- SDK upgrade
- Unity IAP
- Camera Zoom
- Git
- css framework
- screencapture
- Camera Movement
- express
- critical rendering path
- Digital Ocean
- draganddrop
- linux
- MySQL
- Spring Boot
- react
- --watch
- Google Refund
- mongoDB
- docker
- java
- Packet Network
- nodejs
- rpg server
- server
- Unity Editor
- OverTheWire
- unity
- Google Developer API
- springboot
Archives
- Today
- Total
우당탕탕 개발일지
[프로그래머스] Level 3. 숫자 타자 대회 본문
https://school.programmers.co.kr/learn/courses/30/lessons/136797
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
이 문제는 DP (동적 계획법) 을 사용해야 하는 문제이다. 첫번째 문자열부터 시작해서, 결과값을 저장한다. 다음 문자열을 검사할 때, 이전 기록을 가져와 최적의답을 찾는다.
해결방법
- 3차원 배열 m을 선언한다. m[1][2][3] 은 첫번째 문자열까지 눌렀고, 왼손이 2, 오른손이 3일때의 최솟값이다.
- 우리의 목표는 m[문자열사이즈] 에서의 최솟값을 찾는 것이다.
- m[0][4][6] = 0 을 넣는다. 이는, 시작할때 왼손에 4, 오른손에 6이 들어있음을 의미한다.
- 이제 문자열을 하나씩 돌면서 왼손 0~9, 오른손0~9를 모두 검사한다.
- 만약 왼손과 오른손이 같거나, 값이 매겨지지 않았다면(INT_MAX. 경로가 없다는 의미) 패스한다.
- 왼손이 간다고 가정했을때, 도달할 배열은 m[현재문자열+1][next숫자][오른손] 이다.
- 이미 저장되어있는 경우, 최솟값 vs m[현재문자열][현재왼손][현재오른손] + 왼손을 next숫자로 이동시키는 cost 두개를 비교하여 최솟값을 골라 m[현재문자열+1][next숫자][오른손] 에 갱신한다. 왼손을 옮겼을 경우이다.
- 오른손도 마찬가지로 계산해준다.
- 모든문자열까지 반복한다.
- 비용을 찾는 것은 직접 찾는것도 있고, costs를 넣는 방법도 있으나 나의 경우 costs 배열을 만들어서 사용했다. 숫자가 작기도 하고, 매번 찾는것보다는 직접 조회하는 것이 더 빠를것 같았다.
#include <string>
#include <vector>
#include <iostream>
#include <climits>
using namespace std;
vector<vector<int>> costs = {{1, 7,6,7, 5,4,5, 3,2,3},
{7, 1,2,4, 2,3,5 ,4,5,6},
{6, 2,1,2, 3,2,3 ,5,4,5},
{7, 4,2,1, 5,3,2, 6,5,4},
{5, 2,3,5, 1,2,4, 2,3,5},
{4, 3,2,3, 2,1,2, 3,2,3},
{5, 5,3,2, 4,2,1, 5,3,2},
{3, 4,5,6, 2,3,5, 1,2,4},
{2, 5,4,5, 3,2,3, 2,1,2},
{3, 6,5,4, 5,3,2, 4,2,1}};
int solution(string numbers) {
vector<vector<vector<int>>> m(numbers.size()+1,vector<vector<int>>(10,vector<int>(10,INT_MAX))); //i : 문자열 수 , j : 왼손 k : 오른손
m[0][4][6] = 0;
for(int i = 1; i<=numbers.size(); i++){
int n = numbers[i-1]-'0';
for(int j =0; j<10; j++){
for(int k= 0; k<10; k++){
if(j == k || m[i-1][j][k] == INT_MAX) continue; //두손이 겹치거나, 경우의수에 없을 경우
m[i][n][k] = min(m[i][n][k],m[i-1][j][k]+costs[j][n]); //왼손
m[i][j][n] = min(m[i][j][n], m[i-1][j][k] + costs[k][n]); //오른손
}
}
}
int answer = INT_MAX;
for(int i = 0 ; i<10; i++){
for(int j= 0; j<10; j++){
int val = m[numbers.size()][i][j];
if(val < answer) answer = val;
}
}
return answer;
}
마무리하며
dp는 나에게 정말 어려운 알고리즘이다.. 이것도 정답을 보고 깨우친건데, 처음 코드를 봤을땐 이해가 안될정도였다. 비슷한 dp문제를 많이 풀어보고 익혀야 할 것 같다.
'Algorithm(c++) > Level 3' 카테고리의 다른 글
[프로그래머스] Level 3. 부대 복귀 (2) | 2025.02.04 |
---|---|
[프로그래머스] Level 3. 양과 늑대 (1) | 2025.02.04 |
[프로그래머스] Level 3. 섬 연결하기 (1) | 2025.01.30 |
[프로그래머스] Level 3. 길 찾기 게임 (1) | 2025.01.28 |
[프로그래머스] Level 3. 상담원 인원 (1) | 2025.01.26 |