Notice
Recent Posts
Recent Comments
«   2024/09   »
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
29 30
Tags
more
Archives
Today
Total
관리 메뉴

No Limitation

[Greedy] 멀티탭 스케줄링 - 백준 본문

프로그래밍

[Greedy] 멀티탭 스케줄링 - 백준

yesungcho 2022. 2. 11. 12:57

https://www.acmicpc.net/problem/1700

 

1700번: 멀티탭 스케줄링

기숙사에서 살고 있는 준규는 한 개의 멀티탭을 이용하고 있다. 준규는 키보드, 헤어드라이기, 핸드폰 충전기, 디지털 카메라 충전기 등 여러 개의 전기용품을 사용하면서 어쩔 수 없이 각종 전

www.acmicpc.net

 

본 문제를 푼 관점은 다음과 같이 풀어보았습니다.

 

처음에는 단순 완전 탐색 문제라고 생각을 했습니다. 

 

예를 들어보면

 

다음과 같은 예제가 있다고 하면

현재는 2, 1, 3 제품에 대한 멀티탭을 꽂은 상황입니다. 

여기서 예를 들어 다음으로 4를 꽂아야 할 차례인데 4는 현재 멀티탭을 꽂을 곳이 없습니다. 따라서 코드를 빼야하는 상황이 생기는데 이 코드를 빼는 횟수를 최소화를 해야합니다. 

 

그래서, 처음으로는 단순하게 현재 2,1,3에서 앞으로 가장 등장횟수가 적은 얘, 예를 들어 이 문제에서는 2, 1, 3 셋다 한 번씩만 등장하므로 아무거나 빼도 된다고 생각해서 2를 뽑았습니다.

 

즉, 

다음에서 4를 대체할 때 4를 포함한 남은 리스트에서 

현재 꽂혀 있는 애들 중 가장 등장 횟수가 적은 애를 교체하는 것입니다. 

다음과 같이 구성한 코드는 다음과 같습니다. 

 

### Brute Force로 풀기, 22%에서 실패
from collections import Counter
n, k = [int(x) for x in input().split()]
num_list = [int(x) for x in input().split()]

current = []

i = 0

while True :
    if len(current) == n :
        break
    if num_list[i] not in current :
        current.append(num_list[i])
    i += 1

def find(before,after,target) :
    dics = Counter(after)
    mins = float('inf'); answer = 0;
    for b in before :
        if mins > dics[b] :
            mins = dics[b]
            answer = b
    before[before.index(answer)] = target
    return before
    
cnt = 0
while True :
    if i == len(num_list) :
        break
    target = num_list[i]
    if target not in current :
        current = find(current, num_list[i:], target)
        cnt += 1
    i += 1

print(cnt)

하지만 22%에서 실패가 떠가지고 어떤 것이 문제인지를 살펴보았습니다.

 

여기서 최적이 꼭 카운트로 계산이 될까? 라는 의문이 들었고

혹시 유사한 반례가 있나 찾아보니

 

다음과 같은 반례를 풀지 못하였습니다. 

2 15
3 2 1 2 1 2 1 2 1 3 3 3 3 3 3

 

이 경우 실제 정답은 2가 나오지만 제 알고리즘에서는 7이 나왔습니다.

즉 제 알고리즘이 최적을 보장하지 못하였습니다.

 

그래서 생각을 바꾸어보았습니다.

 

현재 꽂혀 있는 플러그에서 가장 나중에 등장하는 애를 바꾸는 것이 최적일 것이라는 생각이 들었습니다. 

 

예를 들면 위 예제를 다시 보면

다음 교체 대상 4를 기준으로 2, 1, 3의 거리를 계산하면

1이 가장 먼 것을 확인할 수 있습니다.

따라서 1을 교체하는 것으로 문제를 바꾸었더니

다행히 통과를 할 수 있었습니다.

구현 코드는 다음과 같습니다. 

 

n, k = [int(x) for x in input().split()]
num_list = [int(x) for x in input().split()]

## 현재 것을 만들어놓기
current = []
i = 0

while True :
    if len(current) == n :
        break
    if num_list[i] not in current :
        current.append(num_list[i])
    i += 1

def find(before, after, target) :
    maxs= 0
    for b in before :
        try :
            k = after.index(b)
            if maxs < k :
                maxs = k
                answer = b
        except :
            answer = b
            break
    before[before.index(answer)] = target
    return before

cnt =0
while True :
    if i == len(num_list) : break
    target = num_list[i]
    if target not in current :
        current = find(current, num_list[i:], target)
        cnt += 1
    i += 1

print(cnt)

 

'프로그래밍' 카테고리의 다른 글

[Binary search] 랜선 자르기 - 백준  (0) 2022.02.11
[Binary Search] 입국 심사 - 프로그래머스  (0) 2022.02.11
[DP] BOJ 거리 - 백준  (0) 2022.02.04
[DP] 1, 2, 3 더하기 4 - 백준  (0) 2022.02.04
[DP] 퇴사2 - 백준  (0) 2022.02.04