[2023 KAKAO BLIND RECRUITMENT] 이모티콘 할인행사

최민길(Gale)·2023년 2월 23일
1

알고리즘

목록 보기
43/172

문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/150368

[이 문제는 프로그래머스에서 푼 문제입니다.]
이 문제는 중복 순열을 이용한 완전 탐색방법으로 풀 수 있습니다. 이 문제는 언뜻 봤을 때 시간 초과가 날 수도 있겠다고 생각할 수 있습니다. 하지만 깊게 들여다보면 완전탐색으로 진행해도 시간 초과가 나지 않는다는 것을 알 수 있습니다.

이 문제는 이모티콘이 가질 수 있는 할인율이 4개이고, 이모티콘의 개수가 7개이기 때문에 모든 이모티콘의 할인율을 적용시킨 총 케이스의 수는 4^7, 즉 4개의 원소들 중에서 7개의 수를 뽑는 중복 순열과 같은 경우의 수입니다. 따라서 중복순열을 구현하여 모든 테스트 케이스를 구한 후 각 케이스 별 유저들의 값들을 기록하여 조건에 맞게 처리하면 됩니다.

다음은 코드입니다.

import java.util.*;

class Solution {
    // 이모티콘 할인율 배열
    static int[] discounts = { 10, 20, 30, 40 };
    // 중복순열 결과 담을 임시 배열
    static int[] result = new int[7];
    // 이모티콘 총 경우의 수
    static int fin;
    // 이모티콘 별 모든 할인율 적용 케이스
    static ArrayList<int[]> res = new ArrayList<>();
    
    public int[] solution(int[][] users, int[] emoticons) {
        int[] answer = {0,0};
        // 유저 수
        int n = users.length;
        // 이모티콘 수
        int m = emoticons.length;
        
        // 이모티콘 총 경우의 수
        fin = (int) Math.pow(4,m);
        
        // result에 모든 경우의 수 중복 순열로 추가
        permutation_with_repetition(0, 4, m);
        
        // 모든 경우의 수에 따른 유저들의 최댓값 계산
        for(int i=0;i<fin;i++){
            int[] curr = res.get(i);
            int userNum = 0;
            int profitSum = 0;
            
            // 유저 별 케이스에서 구매액 계산
            for(int j=0;j<n;j++){
                int total = 0;
                
                for(int k=0;k<curr.length;k++){
                    // 구매 가능 비율이면 구매
                    if(users[j][0] <= curr[k]){
                        total += emoticons[k]*(100 - curr[k])/100;
                    }
                    
                    // 구매액을 넘겼으면 가입
                    if(users[j][1] <= total){
                        total = 0;
                        userNum++;
                        break;
                    }
                }
                
                // 수입 추가
                profitSum += total;
            }
            
            // answer의 값과 비교하여 최댓값 추가
            if(answer[0] < userNum){
                answer[0] = userNum;
                answer[1] = profitSum;
            }
            else if(answer[0] == userNum){
                if(answer[1] < profitSum){
                    answer[0] = userNum;
                    answer[1] = profitSum;
                }
            }
        }
        
        
        return answer;
    }
    
    private static void permutation_with_repetition(int cnt, int n, int r) {
        // r개를 선택했을 때 결과 배열에 지금까지 지나온 값들 저장
        if (cnt == r) {
            int[] tmp = result.clone();
            res.add(tmp);
            return;
        }
        // 중복순열이기 때문에 처음부터 탐색
        for (int i = 0; i < n; i++) {
            // 현재 cnt에 값 추가
            result[cnt] = discounts[i];
            // 이어서 재귀호출
            permutation_with_repetition(cnt + 1, n, r);
        }
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글

관련 채용 정보