Sage

[Algorithem] KOI 2014 지역본선 초등부 본문

Algorithem

[Algorithem] KOI 2014 지역본선 초등부

Naram 2017. 11. 21. 09:50
1번 과자


풀이

고려해야할 경우는 2가지이다.

첫째, K × N > M인 경우 돈이 부하여 부모님에게 돈을 K × N - M 받아야 된다.

둘째, 에 K × N ≦ M인 경우, 과자를 사기에 돈이 분하여 돈을 받지 않아도 된다. 

#include <stdio.h>

int main()
{
    int K;    // 과자 한 개의 가격
    int N;    // 사려고 하는 과자의 개수
    int M;    // 현재 동수가 가진 돈

    scanf("%d %d %d", &K, &N, &M);
    
    // 삼항연산자
    (K * N) >= M ? printf("%d", K * N - M) : printf("0");

    return 0;
}



2번 자리배정



풀이

대기 번호는 (1,1)에서 시작하여 (1,2), (1,3), (1,4), (1,5) ,.... 순으로 가하다가 (1,R)에서 방 향을 바꿔 (2,R) , (3,R) ... 순으로 나아가게 된다. 이게 대기번호를 한 단계씩 려가면서 시뮬레해 대기번호에 른 좌표를 구하는 방법이다.

#include <stdio.h>
#define N 1024
int arr[N][N];

int main()
{
    int p = 0, q = 0;   // p = y의 좌표, q는 x의 좌표
    int C, R, K, count = 1;   // C = 가로, R = 세로, K = 대기번호
    scanf("%d %d %d", &C, &R, &K);
    
    // 관객에게 좌석을 배정할 수 없는 경우
    if(C * R < K)
    {
        printf("0");
        return 0;
    }
    
    arr[p][q] = count++;
    while(count <= C * R && K + 1 != count)
    {
        while(arr[p][q+1] == 0 && q + 1 < R && K + 1 != count) arr[p][++q]=count++;    // 오른방향
        while(arr[p+1][q] == 0 && p + 1 < C && K + 1 != count) arr[++p][q]=count++;    // 아랫방향
        while(arr[p][q-1] == 0 && q > 0 && K + 1 != count) arr[p][--q]=count++;    // 왼쪽방향
        while(arr[p-1][q] == 0 && p > 0 && K + 1 != count) arr[--p][q]=count++;    // 윗방향
    }
    printf("%d %d", p + 1, q + 1);
    return 0;
}



3번 개미



풀이

그림을 보고 x좌표와 y좌표가 서로 독립적인 것을 눈치채지 못하는 함정에 빠질 수 있다.

서로 독집적인 x좌표와 y좌표는 따로 계산을 할 수 있다.

개미의 최종적인 x좌표를 구하는 방법은 다음과 같다.

개미가 격자 공간에서 x좌표의 경계(x = 0 or x = w)에 닿는 횟수를 계산한다. cx를 그 횟수라고 할 때 값은 cx = (p + t) / w 이며, t 시간이 지난 뒤 개미의 최종 x 좌표는 아래와 같다.

cx가 짝수일 때: w - ((p +t) % w)

cx가 홀수일 때: ((p +t) % w)

마찬가지의 방법으로 t 시간이 지난 뒤 개미의 최종 y 좌표를 구할 수 있다. 

#include <stdio.h>

int main()
{
    int w, h;    // w = 가로의 길이, h = 세로의 길이
    int p ,q, t;    // p = 초기 x의 좌표값, q = 초기 y의 좌표값, t = 개미가 움직일 시간
    int cx, cy;    // cx = x좌표의 경계에 닿는 횟수, cy = y좌표의 경계에 닿는 횟수
    scanf("%d %d", &w ,&h);
    scanf("%d %d", &p, &q);
    scanf("%d", &t);
    
    cx = (p + t) / w;    // x좌표의 경계에 닿는 횟수
    cy = (q + t) / h;    // y좌표의 경계에 닿는 횟수
    
    if(cx % 2 == 0)
        p = (p + t) % w;    // cx가 짝수일 때, 횟수 계산
    else
        p = w - ((p + t) % w);    // cx가 홀수일 때, 횟수 계산
    
    if(cy % 2 == 0)
        q = (q + t) % h;    // cy가 짝수일 때, 횟수 계산
    else
        q = h - ((q + t) % h);    // cy가 짝수일 때, 횟수 계산
    
    printf("%d %d", p, q);
    return 0;
}


4번 저울



풀이

그래프로 그려서 문제를 풀면 쉽게 풀릴 수 있다. N 개의 물건은 노드로 표현하고, 각 물건 무게 사이의 관계는 단방향 간선으로 표현을 한다.

[x] > [y]와 같은 입력이 주어졌을 때, 이것을 x 노드에서 y 노드로 가는 단방향 간선으로 표현한다. 이런 방법으로 입력 받은 물건들의 무게 관계를 그래프로 표현하고, DFS나 BFS 알고리즘을 사용하여 답을 구할 수 있다.

#include <stdio.h>
#define Num 128
int arr[Num][Num];

int main()
{
    int N, M;    // N = 물건의 개수, M = 물건 쌍의 개수
    scanf("%d %d", &N, &M);
    
    // 그래프를 인접행렬로 표현한다.
    for(int i = 1, x, y; i <= M; i++)
    {
        scanf("%d %d", &x, &y);
        arr[x][y] = 1;
    }
    
    for(int i = 1; i <= N; i++)
    {
        for(int j = 1; j <= N; j++)
        {
            if(arr[j][i])
            {
                for(int k = 1; k <= N; k++)
                    if(arr[i][k]) arr[j][k] = 1;
            }
        }
    }
    
    for (int i = 1; i <= N; i++)
    {
        int count = 0;
        for (int j = 1; j <= N; j++) 
            if (i != j && arr[i][j] + arr[j][i] == 0)
                count++;
        printf ("%d\n",count);
    }
    
    return 0;
}


공부를 하며 문제를 푸는지라 시간이 상당히 걸렸습니다. 도움을 주신 YJH님 감사합니다.

 

※ 문제 출처: 한국 정보 올림피아드, BOJ

Comments