[백준] 1041번 - 주사위 (C언어) - [Gold5]

2023. 5. 24. 00:45·알고리즘

 

input1 output1 input2 output2 input3 output3
2
1 2 3 4 5 6
36 3
1 2 3 4 5 6
69 1000000 50 50 50 50 50 50

해당 문제는 공간 지각 능력을 갖추고 주사위가 탁자 위에 있는 경우와 마주보았을 때의 경우를 동시에 생각해낸다면 해결할 수 있는 문제이다.

 

  • 마주보았을 때의 경우 1 : 마주보는 면은 포함하지 않는다.
    • A~F면이 0~5 순서로 입력된다고 가정하였을 때 
    • A와 F는 0과 5, E와 B는 1과 4, C와 D는 2와3이 마주본다.
  •  주사위가 탁자 위에 있는 경우 : 면이 1개만 보이는 경우, 면이 2개 보이는 경우, 면이 3개 보이는 경우로 나뉜다.
  • N = 1 인 경우
    • 탁자위에 주사위는 1개만 올라가므로 가장 최솟값을 가지는 면이 보여야 한다.
    • 면의 최솟값은 (모든 면의 총합 - 최댓값)으로 구한다.
  • N >= 2 인 경우
    • 보이는 면들의 최솟값 결정
    • 면이 1개만 보이는 경우 : (5N-6)(N-2) (맨 윗면 * 각 옆면)
    • 면이 2개 보이는 경우 : 8N-12 (각 기둥의 꼭짓점을 제외한 면)
    • 면이 3개 보이는 경우 : 4 (꼭짓점)

각 면의 합의 최대는 5000 이므로 다음과 같이 설정한다. 또한 범위 제한에 의해 result 변수는 long long으로 설정한다.

int three = 5000, two = 5000, one = 5000, large = 0;
long long result = 0;

최댓값은 max 함수를 통해 정의한다.

for (int i = 0; i < 6; i++) {
        scanf("%d", &dice[i]);
        result += dice[i];
        large = max(large, dice[i]); 
    }

N = 1 인 경우 (주사위가 1개인 경우)

if (n == 1) { // 주사위가 1개인 경우
        printf("%lld", result - large);
        return 0;
    }

주사위가 마주보는 경우를 없애면서 각 면의 합의 최솟값을 찾는다.

// 마주보는 경우 없애기
    for (int i = 0; i < 6; i++) {
        one = min(one, dice[i]); // 1면 합
        for (int j = i + 1; j < 6; j++) {
            if (i + j == 5) // 마주보는 경우
                continue;
            two = min(dice[i] + dice[j], two); // 2면합
            for (int k = j + 1; k < 6; k++) {
                if (i + k == 5 || j + k == 5) // 마주보는 경우
                    continue;
                three = min(three, dice[i] + dice[j] + dice[k]); // 3면합
            }
        }
    }

도출된 one, two, three 변수를 이용해 위에서 구했던 N >= 2 인 경우에 해당하는 식을 적용한다.

 result = 0;
    result += (5 * (long long)n * n - 16 * n + 12) * one;
    result += 4 * three;
    result += (8 * n - 12) * two;
    printf("%lld", result);

 

전체 소스 코드는 아래와 같다.

#include <stdio.h>
#pragma warning(disable:4996)
#define max(x,y) ((x) > (y) ? (x) : (y)) 
#define min(x,y) ((x) < (y) ? (x) : (y)) 
// 3면이 보이는 주사위 갯수, 2면이 보이는 주사위 갯수, 1면이 보이는 주사위 갯수의 합을 구하는 문제이다.
// 마주보는 면은 포함되선 안된다.
// A-F를 0-5 순서로 입력한다고 가정했을 때,
// A,F는 0과5, E,B는 1과4, C,D는 2와3이 마주본다.
int n;
int dice[6];
int three = 5000, two = 5000, one = 5000, large = 0;
long long result = 0;
int main() {
    int n;
    scanf("%d", &n);
    for (int i = 0; i < 6; i++) {
        scanf("%d", &dice[i]);
        result += dice[i];
        large = max(large, dice[i]); 
    }

    if (n == 1) { // 주사위가 1개인 경우
        printf("%lld", result - large);
        return 0;
    }

    // 마주보는 경우 없애기
    for (int i = 0; i < 6; i++) {
        one = min(one, dice[i]); // 1면 합
        for (int j = i + 1; j < 6; j++) {
            if (i + j == 5) // 마주보는 경우
                continue;
            two = min(dice[i] + dice[j], two); // 2면합
            for (int k = j + 1; k < 6; k++) {
                if (i + k == 5 || j + k == 5) // 마주보는 경우
                    continue;
                three = min(three, dice[i] + dice[j] + dice[k]); // 3면합
            }
        }
    }

    // 3면 : 4, 2면 : 8n-12, 1면 : (5n-6)(n-2)
    result = 0;
    result += (5 * (long long)n * n - 16 * n + 12) * one;
    result += 4 * three;
    result += (8 * n - 12) * two;
    printf("%lld", result);

    return 0;
}

실행결과

CASE1 CASE2 CASE3


 

[1041번]

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

 

1041번: 주사위

첫째 줄에 N이 주어진다. 둘째 줄에 주사위에 쓰여 있는 수가 주어진다. 위의 그림에서 A, B, C, D, E, F에 쓰여 있는 수가 차례대로 주어진다. N은 1,000,000보다 작거나 같은 자연수이고, 쓰여 있는 수

www.acmicpc.net

 

[github]

https://github.com/MinWook6457/

 

MinWook6457 - Overview

MinWook6457 has 20 repositories available. Follow their code on GitHub.

github.com

 

'알고리즘' 카테고리의 다른 글

[백준] 1407번 - 2로 몇 번 나누어질까 (C언어) [Gold4]  (0) 2023.05.27
[백준] 1197번 - 최소 스패닝 트리 (C언어) [Gold4]  (0) 2023.05.26
[백준] 1874번 - 스택 수열 (C언어) [Silver2]  (0) 2023.05.25
[백준] 1913번 - 달팽이 (C언어) [Silver3]  (2) 2023.05.24
[백준] 10989번 - 수 정렬하기 3 (C언어) - [Bronze1]  (0) 2023.05.23
'알고리즘' 카테고리의 다른 글
  • [백준] 1197번 - 최소 스패닝 트리 (C언어) [Gold4]
  • [백준] 1874번 - 스택 수열 (C언어) [Silver2]
  • [백준] 1913번 - 달팽이 (C언어) [Silver3]
  • [백준] 10989번 - 수 정렬하기 3 (C언어) - [Bronze1]
min._.uuk_
min._.uuk_
하루 하나 기록하기
  • min._.uuk_
    기록하는 습관
    min._.uuk_
  • 전체
    오늘
    어제
    • 분류 전체보기 (33)
      • 알고리즘 (15)
      • 자바 스크립트 (2)
      • 인실리코젠 (15)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    백준 #1407번 #재귀함수
    Apache #POI #JAVA #maven
    백준 #BOJ #스택 #수열
    인실리코젠 #크롤링 #SpringBoot #MVC #jQuery
    #BOJ #백준 #10989번 #C언어 #카운팅정렬 #정렬
    백준 #세그먼트 트리 #구간합 #c언어 #골드1 #탐색
    JS #테트리스 #HTML #CSS #추억의 게임
    백준 #동적계획법 #dp #백트래킹 #dfs
    백준 #후위표기식 #스택 #중위표기식 #우선순위 #1918번
    백준 #MST #최소비용신장트리 #크루스칼 #그리디 #알고리즘
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
min._.uuk_
[백준] 1041번 - 주사위 (C언어) - [Gold5]
상단으로

티스토리툴바