https://www.acmicpc.net/problem/2116
2116번: 주사위 쌓기
첫줄에는 주사위의 개수가 입력된다. 그 다음 줄부터는 한 줄에 하나씩 주사위의 종류가 1번 주사위부터 주사위 번호 순서대로 입력된다. 주사위의 종류는 각 면에 적혀진 숫자가 그림1에 있는
www.acmicpc.net
"""
문제
천수는 여러 종류의 주사위를 가지고 쌓기 놀이를 하고 있다.
주사위의 모양은 모두 크기가 같은 정육면체이며 각 면에는 1부터 6까지의 숫자가 하나씩 적혀있다.
그러나 보통 주사위처럼 마주 보는 면에 적혀진 숫자의 합이 반드시 7이 되는 것은 아니다. (내맘대로 만드는 주사위 라는 뜻)
주사위 쌓기 놀이는 아래에서부터 1번 주사위, 2번 주사위, 3번 주사위, … 의 순서로 쌓는 것이다.
쌓을 때 다음과 같은 규칙을 지켜야 한다:
서로 붙어 있는 두 개의 주사위에서 아래에 있는 주사위의 윗면에 적혀있는 숫자는 위에 있는 주사위의 아랫면에 적혀있는 숫자와 같아야 한다.
다시 말해서, 1번 주사위 윗면의 숫자는 2번 주사위 아랫면의 숫자와 같고, 2번 주사위 윗면의 숫자는 3번 주사위 아랫면의 숫자와 같아야 한다.
단, 1번 주사위는 마음대로 놓을 수 있다.
이렇게 쌓아 놓으면 긴 사각 기둥이 된다. 이 사각 기둥에는 4개의 긴 옆면이 있다.
이 4개의 옆면 중에서 어느 한 면의 숫자의 합이 최대가 되도록 주사위를 쌓고자 한다.
이렇게 하기 위하여 각 주사위를 위 아래를 고정한 채 옆으로 90도, 180도, 또는 270도 돌릴 수 있다.
한 옆면의 숫자의 합의 최댓값을 구하는 프로그램을 작성하시오.
<입력>
첫줄에는 주사위의 개수가 입력된다. 그 다음 줄부터는 한 줄에 하나씩 주사위의 종류가 1번 주사위부터 주사위 번호 순서대로 입력된다.
주사위의 종류는 각 면에 적혀진 숫자가 그림1에 있는 주사위의 전개도에서 A, B, C, D, E, F 의 순서로 입력된다.
입력되는 숫자 사이에는 빈 칸이 하나씩 있다.
주사위의 개수는 10,000개 이하이며 종류가 같은 주사위도 있을 수 있다.
<출력>
첫줄에 한 옆면의 숫자의 합이 가장 큰 값을 출력한다.
"""
# 에이와 에프는 실제 값으로 사용을 할수가 없다. 왜냐? 기둥속으로 들어가기 때문 이다.
# 즉, 리스트에서 시작값과 끝값은 마주보는데 사용하고, 세로로 이어진 줄의 합을 계산 해야 한다.
# 주사위배열: (x) (y) (z) (y) (z) (x) 이렇게 쌍을 이룬다는걸 기억하자
# [0 6] [1 3] [2 4] 이렇게 서로 세트가 된다.
'''
5
2 3 1 6 5 4 (2 4) (3 6) (1 5) #총 6번을 계산을 돌려보면 될것 같다
3 1 2 4 6 5 (3 5) (1 4) ()
5 6 4 1 3 2 (5 2) (6 1) ()
1 3 6 2 4 5 (1 5) (3 2) ()
4 1 6 5 2 3 (4 3) () ()
이면 답은 29가 된다. (어째서지?, 우선 모든 주사위가 6이 아니다 , 어쩔수 없이 6을 사용하지 못하는 경우가 존재한다는 말이지...)
그렇다 1층에서 x,y,z 3개의 쌍중에서 어떤걸 기둥의 축으로 삼을지 결정하면, 나머지 것들은 알아서 결정이 된다!
'''
'''
import sys
주사위개수=int(sys.stdin.readline())
층정보=[]
for _ in range(주사위개수):
x1, y1,z1,y2,z2,x2 = map(int,sys.stdin.readline().split())
층정보.append([x1,x2,y1,y2,z1,z2])
print(층정보)
'''
'''
for _ in 층정보:
print(_)
정상적으로 출력이 완료 되었다.
[(2, 4), (3, 6), (1, 5)]
[(3, 5), (1, 4), (2, 6)]
[(5, 2), (6, 1), (4, 3)]
[(1, 5), (3, 2), (6, 4)]
[(4, 3), (1, 5), (6, 2)]
'''
'''
# 6가지 경우의 수를 계산 한다.
# 튜플에서 [0]을 바닥에 까는 경우의수 계산
# 2차원 배열 형태로 들어감 (내용물은 튜플 )
# 일단 한층씩 꺼내는 형태로 진행한다.
max_list=[]#6가지 총합의 경우의수에서 나중에 맥스 함수 사용해서 결과 출력할 에정 (정답지)
일층=층정보[0]
my_dic={0:5, 1:3, 2:4, 4:2, 3:1, 5:0} #서로의 쌍을 찾을때 사용
for i in range(6):#6번 반복이 된다.주사위의 바닥을 하나씩 정했을때 이다.
counter=0
start=일층[i]
for k in range(주사위개수):
bottom=층정보[k][]
top= 층정보[k][]
mlist=[1,2,3,4,5,6]
mlist.remove(bottom)
mlist.remove(top)
counter+=max(mlist)
start=bottom
print(층정보)
'''
"""
정말 화나는점
난 리스트값이 다시 다른리스트의 인덱스 번호가 되어서 a = mlist[0]
mlist2=mlist[a] 이런 꼴이 제일 머리 아프고 구현하기도 너무 어렵다
"""
N = int(input())
dice = []
for _ in range(N):
dice.append(list(map(int, input().split())))
rotate = {0 : 5, 1 : 3, 2 : 4, 3 : 1, 4 : 2, 5 : 0} # 주사위의 아랫면에 따른 윗면 로테이션 등록(리스트 인덱스 기준)
maxnum = 0 # 최대값을 저장해둘 상수 선언
for i in range(6): # 첫 번째 주사위를 기준으로 1~6까지 모두 순회
result = [] #각 주사위마다 옆면의 최대값 1개를 저장해둘 리스트 선언
temp = [1, 2, 3, 4, 5, 6] # 주사위 각 면에 써져있는 1~6
temp.remove(dice[0][i]) # 주사위 아랫면의 숫자 제거
next = dice[0][rotate[i]] # 첫 번째 주사위의 윗면 값 계산
temp.remove(next) # 첫 번째 주사위의 윗면 값 삭제
result.append(max(temp)) # 첫 번째 주사위의 옆면들 중 가장 큰 값 삽입
for j in range(1, N): # 두 번째 주사위부터 마지막 주사위까지 반복
temp = [1, 2, 3, 4, 5, 6]
temp.remove(next) # 현재 주사위의 아랫면 숫자 제거
next = dice[j][rotate[dice[j].index(next)]] # 현재 주사위의 윗면 계산
temp.remove(next) # 현재 주사위의 윗면 삭제
result.append(max(temp)) # 현재 주사위의 옆면들 중 가장 큰 값 삽입
result = sum(result) # 각 주사위마다의 최대값을 모두 더한다.
if maxnum < result: # 이전의 최대값과 현재의 최대값을 비교하여 더 큰 값을 저장한다.
maxnum = result
print(maxnum)
<알고넘어가야 하는점>
나는 주사위에서 아랫면과 밑면을 bottom과 top으로 구분했는데, 그럴 필요가 없이 next 라는 변수를 활용해서 탑 바텀 변수를 설정하였다.(물론 1층에서 밑면을 따로 삭제 해주어야 한다.)
그리고 딕셔너리를 활용해서 주사위의 면이 평행한 부분을 매핑해주었다.(여기 까지는 생각함)
가장 헷갈린 부분은, next = dice[j][rotate[dice[j].index(next)]] # 현재 주사위의 윗면 계산 으로 index를 사용해서 next라는 변수를 가진 해당 리스트에서 요소를찾고 인덱스 번호를 반환하였다. 고려해야할 사항이 3개나 있다 (dice, rotate 딕셔너리, next 변수)
이 부분을 구현하는게 골치아프긴 하였다. 시간내로 풀지 못한 이유라고 생각한다.
'백준 알고리즘 문제풀이' 카테고리의 다른 글
[Python] 1166번: 선물 (0) | 2023.06.24 |
---|---|
[Python] 22238번: 가희와 btd5 (2) | 2023.01.20 |
[Python] 2302번: 극장 좌석 (0) | 2023.01.14 |
[Python] 1966번: 프린터 큐 (0) | 2023.01.01 |
[Python] 1920번: 수 찾기 (0) | 2023.01.01 |