[프로그래머스] Lv2 광물 캐기 (Java)

2023. 9. 4. 17:06·Algorithms(CT)/Programmers
 

프로그래머스

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

programmers.co.kr

 

문제 설명

 

곡괭이 하나를 선택해서 광물 5개를 연속으로 캐고, 다음 곡괭이를 선택해서 5개를 연속으로 캐는 과정을 반복하여, 더 사용할 곡괭이가 없거나, 모든 광물을 캘 때까지 과정을 반복합니다.

마인이 갖고 있는 곡괭이의 개수를 나타내는 배열 picks와 광물들의 순서를 나타내는 문자열 배열 minerals가 매개변수로 주어질 때, 마인이 작업을 끝내기까지 필요한 최소한의 피로도를 return 하는 solution함수를 완성해주세요.

 


접근 방식

  • minerals의 길이가 짧다.(0 <= minerals.length <= 50) -> 완전 탐색 가능
  • 5개 광물마다 다이아, 철, 돌 곡괭이로 캘 경우를 고려하고, 그 다음 5개의 광물을 캘 때 이전의 피로도를 받아서 계산하기 때문에 -> DFS를 사용합니다.
  • 무조건 연속 5개의 광물 캐야함 -> 광물을 5개 단위로 묶음
  • 가진 곡괭이 개수로 캘 수 있을 때까지만 캡니다. -> 캘 수 없는 광물은 버림.  

 

풀이 과정

1. 전체 곡괭이 개수와 광물을 5개씩 묶었을 때 몇 묶음이 나오는지 구합니다.

    그 중 더 작은 값을 n에 넣어, 캘 수 있는 광물까지(n)의 개수를 구해줍니다.

int pickCnt = Arrays.stream(picks).sum();//곡괭이 개수
int bundle = (minerals.lenth-1)/5+1;//광물을 5개씩 묶음
//곡괭이개수와 광물묶음개수 중에 더 작은 걸로 선택
int n = Math.min(pickCnt,bundle);

 

>> 5묶음으로 묶을 때 왜 저렇게 나누지?

더보기

0

0 0

0 0 0

0 0 0 0

0 0 0 0 0

length=1~5까지 다 1묶음이 나와야 함.

그냥 (minerals.length/5)를 해주면 length=4까지는 0이 나오는데 5일때는 1이 나오기 때문에 같은 숫자로 맞춰주기 위해 → (minerals.length-1/5)

 

그리고, 저렇게만 해주면 0묶음이 되기 때문에 +1해서 1묶음으로 만들어 줍니다.

 

2. 광물 5개 묶음씩 자르고, 그 안에 다이아, 철, 돌을 몇 개씩 가지고 있는지 배열에 저장합니다.

    가진 곡괭이로 캘 수 있을 만큼까지만 저장합니다.

코드

더보기
//5개 묶음 당 -> 다이아, 철, 돌 몇 개씩 가지고 있는지 저장.
int[][] mins = new int[n][3];
//기본적으로 광물을 끝까지 저장하지만, 곡괭이 개수를 초과하지 않을 때까지 저장.
for(int i=0;i<minerals.length && i<5*n;i++){
    if(minerals[i].equals("diamond")) mins[i/5][0]++; //0:다이아 개수
    else if(minerals[i].equals("iron")) mins[i/5][1]++;//1:철 개수
    else mins[i/5][2]++;//2: 돌 개수
}

 

3. 이제 묶음 단위로 다이아, 철, 돌 곡괭이를 선택하는 방법을 달리하며 DFS 탐색을 해줍니다.

코드

더보기
//mins:광물 5개씩 묶음 별 각 광물 개수 / picks:곡괭이 개수 / depth:몇번째 묶음 / fitague:현재 피로도 
void dfs(int[][] mins, int[] picks, int depth, int fitague){
    
    if(depth==mins.length){//광물 끝까지 다 조사하면 끝냄.
        if(fitague<minFitague) minFitague=fitague;
        return;
    }
    
    //곡괭이는 다이아(0) -> 철(1) -> 돌(2) 순
    for(int i=0;i<picks.length;i++){
        if(picks[i]==0) continue;// i곡괭이가 없으면 다음 곡괭이로 넘어감.
        
        picks[i]--; //i곡괭이 사용
        dfs(mins,picks,depth+1,fitague+cntFitague(mins[depth],i));
        picks[i]++; //i곡괭이 사용하기 전으로 되돌림.
    }
}

 

4. 현재 피로도 계산함수 cntFitague

코드

더보기
//5개 광물 묶음을 pick곡갱이로 캘 때 피로도
int cntFitague(int[] min5, int pick){
    int fitague=0;
    
    //0:다이아, 1:철, 2:돌
    for(int i=0;i<min5.length;i++){//i:광물
        if(pick<=i) fitague+=min5[i]*1;//곡괭이가 광물보다 세거나 같을때
        else if(pick-i==1) fitague+=min5[i]*5;//곡괭이가 광물보다 1 약할때
        else fitague+=min5[i]*25;//곡괭이가 광물보다 2 약할 때 -> 돌 곡괭이로 다이아 캐려고 할 때
    }
    
    return fitague;
}

 


전체 코드

import java.util.*;
class Solution {
    int minFitague=Integer.MAX_VALUE;//최소 피로도
    public int solution(int[] picks, String[] minerals) {
        
        int pickCnt = Arrays.stream(picks).sum();//곡괭이 개수
        int bundle = (minerals.length-1)/5+1;//광물 5개씩 묶음 개수
        //5개 광물씩 잘랐을 때 몇 묶음의 광물이 있는지 와 비교해서 더 작은 걸로 선택
        int n = Math.min(pickCnt,bundle);
        
        //5개의 광물 당 -> 다이아 몇개, 철 몇 개, 돌 몇개 가지고 있는지
        int[][] mins = new int[n][3];
				//기본적으로 광물을 끝까지 저장하지만, 곡괭이 개수를 초과하지 않을 때까지 저장.
        for(int i=0;i<minerals.length && i<5*n;i++){
            if(minerals[i].equals("diamond")) mins[i/5][0]++;
            else if(minerals[i].equals("iron")) mins[i/5][1]++;
            else mins[i/5][2]++;
        }
        
        dfs(mins,picks,0,0);
        
        return minFitague;
    }
    //mins:광물 5개씩 묶음 별 각 광물 개수 / picks:곡괭이 개수 / depth:몇번째 묶음 / 현재 피로도 
    void dfs(int[][] mins, int[] picks, int depth, int fitague){
        
        if(depth==mins.length){//광물 끝까지 다 조사하면 끝냄.
            if(fitague<minFitague) minFitague=fitague;
            return;
        }
        
        //곡괭이는 다이아(0) -> 철(1) -> 돌(2) 순
        for(int i=0;i<picks.length;i++){
            if(picks[i]==0) continue;// i곡괭이가 없으면 다음 곡괭이로 넘어감.
            
            picks[i]--;
            dfs(mins,picks,depth+1,fitague+cntFitague(mins[depth],i));
            picks[i]++;
        }
    }
    
    //5개 광물 묶음을 pick곡갱이로 캘 때 피로도
    int cntFitague(int[] min5, int pick){
        int fitague=0;
        
        //0:다이아, 1:철, 2:돌
        for(int i=0;i<min5.length;i++){
            if(pick-i<=0) fitague+=min5[i]*1;//곡괭이가 광물보다 세거나 같을때
            else if(pick-i==1) fitague+=min5[i]*5;//곡괭이가 광물보다 1 약할때
            else fitague+=min5[i]*25;//곡괭이가 광물보다 2 약할 때 -> 돌 곡괭이로 다이아 캐려고 할 때
        }
        
        return fitague;
    }
}

'Algorithms(CT) > Programmers' 카테고리의 다른 글

[프로그래머스] Lv2. 단체사진 찍기 (Java)  (0) 2023.09.19
[프로그래머스] Lv2 숫자 블록 (Java)  (0) 2023.09.05
[프로그래머스] Lv.1 추억 점수 (Java)  (0) 2023.08.21
[프로그래머스] Lv1. 달리기 경주 (Java)  (0) 2023.08.21
[프로그래머스] Lv.2 혼자 놀기의 달인 (Java)  (0) 2023.08.04
'Algorithms(CT)/Programmers' 카테고리의 다른 글
  • [프로그래머스] Lv2. 단체사진 찍기 (Java)
  • [프로그래머스] Lv2 숫자 블록 (Java)
  • [프로그래머스] Lv.1 추억 점수 (Java)
  • [프로그래머스] Lv1. 달리기 경주 (Java)
gwee_99
gwee_99
bE bETTER!
  • gwee_99
    얼렁이와 뚱땅이
    gwee_99
  • 전체
    오늘
    어제
    • ====Category====
      • Algorithms(CT)
        • Programmers
        • Baekjoon
        • Goorm
      • Web
        • Error 해결
      • BackEnd
        • Spring
        • JPA
      • FrontEnd
        • HTML.CSS
        • JavaScript
      • Language
        • Java
      • Cloud
      • CSTS
      • Books
        • IT 5분 잡학사전
      • 일상
  • 블로그 메뉴

    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    BOJ
    Greedy
    구름
    DFS
    존안님
    LV.2
    호텔 대실
    Til
    자바
    java
    IT 잡학사전
    노마드코더
    BFS
    따라하며 배우는 html css
    제대로 파는 자바스크립트
    스택
    인프런
    LV.3
    프로그래머스
    Lv.1
    lv2
    구름톤 챌린지
    IT 5분 잡학사전
    HTML
    개발자북클럽
    코딩테스트
    lv.4
    DP
    백준
    그리디
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gwee_99
[프로그래머스] Lv2 광물 캐기 (Java)
상단으로

티스토리툴바