본문 바로가기

코딩/프로그래머스

[프로그래머스/JAVA] 코딩테스트 연습 > 2025 프로그래머스 코드챌린지 2차 예선 > 서버 증설 횟수 (by 다알쥐AI)

728x90
반응형

[서버 증설 횟수] 코딩테스트 연습 > 2025 프로그래머스 코드챌린지 2차 예선 > 서버 증설 횟수

 

 

※ 주의 : 문제풀이 방법은 다양합니다. 참고만 해주세요 

[문제설명]

더보기

당신은 온라인 게임을 운영하고 있습니다. 같은 시간대에 게임을 이용하는 사람이 m명 늘어날 때마다 서버 1대가 추가로 필요합니다. 어느 시간대의 이용자가 m명 미만이라면, 서버 증설이 필요하지 않습니다. 어느 시간대의 이용자가 n x m명 이상 (n + 1) x m명 미만이라면 최소 n대의 증설된 서버가 운영 중이어야 합니다. 한 번 증설한 서버는 k시간 동안 운영하고 그 이후에는 반납합니다. 예를 들어, k = 5 일 때 10시에 증설한 서버는 10 ~ 15시에만 운영됩니다.

하루 동안 모든 게임 이용자가 게임을 하기 위해 서버를 최소 몇 번 증설해야 하는지 알고 싶습니다. 같은 시간대에 서버를 x대 증설했다면 해당 시간대의 증설 횟수는 x회입니다.

다음은 m = 3, k = 5 일 때의 시간대별 증설된 서버의 수와 증설 횟수 예시입니다.


모든 게임 이용자를 감당하기 위해 최소 7번 서버를 증설해야 하며, 이보다 적은 수의 서버 증설로는 모든 게임 이용자를 감당할 수 없습니다.

0시에서 23시까지의 시간대별 게임 이용자의 수를 나타내는 1차원 정수 배열 players, 서버 한 대로 감당할 수 있는 최대 이용자의 수를 나타내는 정수 m, 서버 한 대가 운영 가능한 시간을 나타내는 정수 k가 주어집니다. 이때, 모든 게임 이용자를 감당하기 위한 최소 서버 증설 횟수를 return 하도록 solution을 완성해 주세요.


제한사항

  • players의 길이 = 24
    • 0 ≤ players의 원소 ≤ 1,000
    • players[i]는 i시 ~ i+1시 사이의 게임 이용자의 수를 나타냅니다.
  • 1 ≤ m ≤ 1,000
  • 1 ≤ k ≤ 24

테스트 케이스 구성 안내

아래는 테스트 케이스 구성을 나타냅니다. 각 그룹 내의 테스트 케이스를 모두 통과하면 해당 그룹에 할당된 점수를 획득할 수 있습니다.



입출력 예



입출력 예 설명

입출력 예 #1

  • 문제의 예시와 같습니다.

입출력 예 #2

  • 총 11번 서버를 증설해야 합니다.
    • 3 ~ 4시: 2번
    • 5 ~ 6시: 2번
    • 7 ~ 8시: 3번
    • 15 ~ 16시: 1번
    • 18 ~ 19시: 2번
    • 20 ~ 21시: 1번

입출력 예 #3

  • 총 12번 서버를 증설해야 합니다.
    • 5 ~ 6시: 2번
    • 9 ~ 10시: 1번
    • 11 ~ 12시: 5번
    • 13 ~ 14시: 2번
    • 15 ~ 16시: 1번
    • 23 ~ 24시: 1번

[간단설명]

매시간 이용자 수에 따른 최소 서버 증설 횟수 구하기

 

[접근방법]

1. 큐를 만든다.

2. 현재 이용자수가 최대 이용자수보다 크면 서버를 증설한다.

    2.1. 큐에 저장된 서버를 계산한다.

    2.2. 증설개수가 0보다 크면 서버를 신규 증설한다.

3. 큐에 저장된 서버의 시간을 계산해준다.

4. 최소 서버 증설 횟수를 리턴한다. 

 

[주의사항]

1. 리스트로 구현하면, size를 구할때, get, remove할 때, 원하는 데이터를 엑세스하기 쉽지 않다.

2. 큐나 우선순위큐를 사용해서 구현해보자.

 

[소스공개]

import java.util.*;
class Solution {
    public int solution(int[] players, int m, int k) {
    
        // 큐 만들기 
        Queue<int[]> que = new LinkedList<>();
        int queSize = 0;
        int queCnt = 0;
        
        // 변수 선언 
        int maxPlayers = m;  // 최대 이용자수
        int totolServer = 0; // 최소 서버 증설 횟수 
        for(int p : players){
            // 현재 이용자가 최대 이용자수보다 크거나 같으면
            if(p>=maxPlayers){
                int addServer = p/m; // 현재 필요한 서버
                queSize = que.size();
                queCnt = 0;
            
                // 현재 필요한 서버에서, 큐에 저장된 서버만큼 빼준다
                while(queCnt < queSize){
                    int[] now = que.poll();
                    addServer -= now[0];
                    que.add(now);
                    queCnt++;
  
                }
                // 새로 서버를 증설해야하면,
                // 최소 서버 증설 횟수 증가, 최대 이용자수 증가 
                if(addServer>0){
                    que.add(new int[]{addServer,k});
                    totolServer+=addServer;
                    maxPlayers+=addServer*m;
                }
                
            }
            
            queSize = que.size();
            queCnt = 0;
            // 큐의 서버에 저장된 대여 시간 계산 
            while(queCnt < queSize){
                int[] now = que.poll();
                now[1]-=1;
                // 대여 시간 만료
                if(now[1]==0){
                    maxPlayers-=now[0]*m;
                }else{
                // 아니면 -1 시간을 다시 큐에 넣어준다
                    que.offer(now);
                }
                queCnt++;
            }
        }
        // 최소 서버 증설 횟수 리턴
        return totolServer;
    }
}

 

[실행결과]

 

 

 

 

반응형