[그리디] C11 백준 1700 멀티탭 스케줄링 풀이

New Jenice!·2024년 11월 1일
0

Daily Algorithm

목록 보기
12/71
post-thumbnail

문제

풀이 과정

  • 먼저, 실패한 코드
#include <stdio.h>

#define MAX 101

int n,k;
int check[MAX];

int main() {
    scanf("%d %d", &n, &k);
    for (int i=0; i<k; i++) {
        scanf("%d", &check[i]);
    }
    
    int multi[n];
    int cnt = 0;
    int result = 0;
    for (int i=0; i<k; i++) {
        if (cnt < n) {
            int flag = 0;
            for (int j=0; j<cnt; j++) {
                if (multi[j] == check[i]) {
                    flag = 1;
                }
            }
            if (flag == 0) {
                multi[cnt++] = check[i];
            }   
        } else {
            int flag = 0;
            for (int j=0; j<n; j++) {
                if (multi[j] == check[i]) {
                    flag = 1;
                }
            }
            if (flag == 0) {
                multi[n-1] = check[i];
                result++;
            }
        }
    }
    
    printf("%d", result);
    
    return 0;
}
  • check를 순환하면서
    • multi 배열이 n이 아니고(꽂을 곳이 있고), multi 배열에 check[i]와 같은 값이 없다면 multi 배열에 check 배열의 값을 넣음
    • multi 배열이 꽂을 곳이 없고, multi 배열에 check[i]와 같은 값이 없다면 multi 배열의 마지막을 check[i]값으로 변경하고 카운팅
  • 그러면 내 예상은
2, 7

Check 2 3 2 3 1 2 7 
Multi 0 0 일 때,

Multi 2 0
Multi 2 3
2, 3 은 Multi 배열에 이미 있기 때문에 패스

Multi 2 1, result++
2는 있기 때문에 패스

Multi 2 7, result++

result = 2
  • 이런 방식을 생각했다
  • 하지만 이 코드엔 간과한 점이 있었으니(ㅠㅠ)
    • 그건 바로 플러그 교체할 때 또 사용되는 건지 아니면 사용이 안되는건지 확인하는 로직이 빠져 버렸다
  • 예를 들어 보자
Check 2 3 2 3 1 3 3 
Multi 0 0 일 때,

Multi 2 0
Multi 2 3
2, 3 은 Multi 배열에 이미 있기 때문에 패스

Multi 2 1, result++
Multi 2 3, result++
3 은 Multi 배열에 이미 있기 때문에 패스

result = 2 인데

사실상 최소값은,

Multi 2 0
Multi 2 3
2, 3 은 Multi 배열에 이미 있기 때문에 패스

Multi 1 3, result++
3, 3 은 Multi 배열에 이미 있기 때문에 패스

result = 1 이여야 함
  • 그렇다면 그 뒤에 나오는 애들의 빈도수를 확인하고 넣어야 하나?
    • 멀티탭은 순서대로 넣어야 하기 때문에, 빈도수 확인은 필요가 없다
    • multi 배열에 있는 값이 check 배열에 있는 값에서 얼마나 가까운 곳에 있는지 확인하면 된다
  • 예를 들어 보자
Check 2 3 4 2 5 3 6
Multi 0 0 일 때,

Multi 2 0
Multi 2 3

Check 4 2 5 3 6
Multi 2 3

이제 4를 넣어야 하는데, 멀티탭은 꽉 찼다.
그럼 Mutl에서 어떤 값을 지우고 4를 넣어야 할까?
1. 더이상 사용되지 않는 값이 있으면, 그 값으로 교체
2. 없다면, 가장 빨리 사용될 값으로 교체 (오래 유지 하는게 핵심이기 때문)

그럼 각각의 값을 살펴보자

Multi 2 3
3 은 Check[5] 에서 다시 사용
2 는 Check[3] 에서 다시 사용
그렇다면? 3이 더 늦게 사용되므로 2를 교체해준다

Check 2 5 3 6
Multi 4 3
4가 존재하지 않으니 4를 교체

Check 5 3 6
Multi 2 3
2가 존재하지 않으니 2를 교체

3 패스

Check 6
Multi 5 3
둘 다 존재 하지 않으니 아무거나 교체

정답 코드

#include <stdio.h>

#define MAX 101

int n,k;
int check[MAX];

int main() {
    scanf("%d %d", &n, &k);
    for (int i=0; i<k; i++) {
        scanf("%d", &check[i]);
    }
    
    int multi[n];
    int cnt = 0;
    int result = 0;
    for (int i=0; i<k; i++) {
        int cur = check[i];
        
        int flag = 0;
        for (int j=0; j<cnt; j++) {
            if (multi[j] == cur) {
                flag = 1;
                break;
            }
        }
        if (flag == 1) continue;
        if (cnt < n) {
            multi[cnt++] = cur;
            continue;
        }
        
        int last_idx = -1;
        int farthest = -1;
        for (int a=0; a<n; a++) {
            int next_use = 0;
            for (int b=i+1; b<k; b++) {
                if (multi[a] == check[b]) {
                    next_use = b;
                    break;
                }
            }
            if (next_use == 0) {
                last_idx = a;
                break;
            }
            
            if (next_use > farthest) {
                farthest = next_use;
                last_idx = a;
            }
        }
        
        multi[last_idx] = cur;
        result++;
    }
    
    printf("%d", result);
    
    return 0;
}
profile
Embedded Software Engineer

0개의 댓글