BOJ 28457 Every? Only One's Marble Python

가나다·2023년 8월 16일
0

알고리즘

목록 보기
12/14

문제




예제 입력
6 20000 10000 4
1 2000
4 1
2 3000
3 5000
L 500
L 1000
L 1500
G
L 1000
L 2000
G
L 3000
L 2000
G
L 4000
L 6000
G
L 3000
L 6000
L 9000
18
1 1
3 1
3 2
3 3
1 1
1 1
1 2
2 1
6 5
6 6
3 1
5 4
1 1
2 3
6 3
5 5
2 1
1 3

출력
WIN

접근

입력받은 주사위만큼 움직이며 도착 지점에 정보에 따라 행동을 취해가며 승리 조건에 따라 WIN 또는 LOSE를 출력한다

승리 조건
1. 주사위를 던 짓 횟수만큼 움직이며(모든 땅을 다 사도 움직여야 함) 은행에 돈 주기, 사회복지 기금에 돈 기부하기를
실행할 때 돈이 모자라면 LOSE
2. 주사위 횟수를 채우고 일반칸에 사지 않은 땅이 있다면 LOSE (중간에 일반 땅에 도착했을 때
돈이 부족하면 사지 않고 넘어가도 됨)

기타 조건
1. 무인도에 도착 시 주사위를 3번까지 굴리고 3번 안에 두 주사위가 같은 숫자 면 탈출한다
2. 우주여행칸 도착 시 시작칸으로 이동 후 주사위를 굴린다
3. 일반칸에 도착 시 해당 칸을 구매하기 위한 돈보다 현재 가진 돈이 많으면 무조건 사야 함
4. G 칸(황금 열쇠)은 도착할 때마다 입력받은 순서대로 뽑으며 마지막 장을 뽑으면 맨 첫 장부터 다시 뽑는다
5. 황금열쇠 4번 조건으로 앞으로 n 칸 이동 시 그 칸에 대한 행동을 바로 해야 함

코드

import sys

input = sys.stdin.readline
n,money,startprice,g = map(int,input().split()) 
#순서대로 보드의 크기,맨 처음 들고있는 돈,시작지점을 지나거나 도착시 받는돈,
nboardsize = 4*n-8 #일반 칸의 크기 (시작지점,무인도 등등..을 제외한 크기)
goldkey = [input().rstrip() for _ in range(g)]

Specialplacd = [input().strip() for _ in range(nboardsize)]
mapsize = 4*n-4 #보드의 최종 크기 
board = ['']+['' for _ in range(mapsize)] # 인덱스를 맞추기 위해 맨 첫칸은 빈칸+입력받은 정보로 초기화
chkbuy = [True for _ in range(len(board))]
#보드의 특수 칸은 공식이 정해져 있어 해당 공식대로 초기화
for x in range(1,len(board)):
    if x == 1:
        board[x] = 'S1'
    elif n == x:
        board[x] = 'S2'
    elif 2*n-1 == x:
        board[x] = 'S3'
    elif 3*n-2 == x:
        board[x] = 'S4'
    else:
        board[x] = Specialplacd.pop(0)
        if board[x] == 'G':
            chkbuy[x] = True
        elif board[x].split()[0] == 'L':
            chkbuy[x] = False

now = 1 #시작위치
savs3 = 0 #3번째 특수칸에 저장될 변수
bank = 0 #은행에 저장될 변수
gidx = 0 # 황금열쇠를 순서대로 뽑기 위한 인덱스 저장
dicelst =[list(map(int,input().split())) for _ in range(int(input()))] #주사위 입력
 

isgetdice = True # 주사위를 굴리지 않고 칸을 이동할 수 있기 때문에 그에 따른 boolean 변수
def getdice(): #주사위 굴리기 입력받은 주사위를 순서대로 굴려주고 전부 소진시 -1
    if len(dicelst) == 0:
        return -1
    d1,d2 = dicelst.pop(0)

    return [d1+d2,d1==d2]

def island(): #무인도 주사위를 최대 3번 굴리고 같은 숫자가 나오면 반복문 종료
    global isgetdice
    isgetdice =True
    for _ in range(3):
        wer = getdice()
        
        if wer == -1:
            break
        elif wer[1]:
            break

prres = False # 주사위 전부 소진하기 전에 패배조건에 걸리면 바로 출력해주고 일반칸 연산X
while True:

    if isgetdice:
        wer = getdice()
        if wer == -1:
            break
        now +=wer[0]

    if now > mapsize:
        while now > mapsize:
            money += startprice
            now -= mapsize
    if now ==0:
        now +=1    
    
    
    nowinfo = board[now].split()
    # L은일반땅이기에 보유한 돈을 비교하여 구매 할 수 있으면 바로 구매한다
    if nowinfo[0] =='L' and not chkbuy[now] and int(nowinfo[1]) <= money:
        money -= int(nowinfo[1])
        chkbuy[now] = True
    elif nowinfo[0] == 'G':# 황금열쇠 처리

        nowinfo.append(goldkey[gidx].split()[0])
        nowinfo.append(goldkey[gidx].split()[1])
        gidx +=1
        if gidx >= len(goldkey):
            gidx = 0
        if nowinfo[1] == '1':
            bank -= int(nowinfo[2])
            money += int(nowinfo[2])
        elif nowinfo[1] == '2':
            bsav = int(nowinfo[2])
            if bsav > money:
                print('LOSE')
                prres = True
                break
            bank += bsav
            money -= bsav
        elif nowinfo[1] == '3':
            
            s3pr = int(nowinfo[2])
            if s3pr > money:
                print('LOSE')
                prres = True
                break
            savs3 += s3pr
            money -= s3pr
        elif nowinfo[1] == '4':
            now += int(nowinfo[2])
            isgetdice = False
            continue
            
    else:# 특수칸 처리
        if nowinfo[0] == 'S2':
            island()
        elif nowinfo[0] == 'S3':
            money += savs3
            savs3 = 0
        elif nowinfo[0] == 'S4':
            money += startprice
            now = 1
            isgetdice = False 
            continue
    isgetdice = True  #주사위를 던지지 않고 이동시 도착 칸의 행동을 실행하고 주사위 굴리기

if not prres:
    if False in chkbuy: # 구매하지 않은 땅이 있다면 LOSE 그렇지 않으면 WIN
        print('LOSE')
    else:
        print('WIN')

결과

여태껏 풀었던 문제 중에 지문이 제일 길고 코드도 길었다 그래서 테스트 코드를 그대로 제출하는 등
실수가 생각보다 많이 나왔던 문제

profile
가나다

1개의 댓글

comment-user-thumbnail
2023년 8월 16일

공감하며 읽었습니다. 좋은 글 감사드립니다.

답글 달기