반응형

문제 설명

땅 위에 달팽이가 있으며, 이 달팽이는 V미터까지 올라가게 되는데

낮에 A미터를 올라가고 밤에 B미터를 내려간다. 단, 정상에 도착했다면 내려가지 않는다.

이 때, 달팽이가 V미터까지 올라가는데 총 며칠이 걸리는지 구하면 된다.


풀이 과정

낮에는 무조건 올라가기만 하고 밤에는 무조건 내려가기만 한다.

그래서 낮에 올라간 높이가 그 날의 최대 높이가 될 것이고, 정상에 도착하더라도 무조건 낮에 도착을 하게된다.

 

그래서 사실상 달팽이가 올라가야 하는 최종 높이V-B미터가 된다.

그리고 하루동안 올라갈 수 있는 높이는 A-B미터로 한정되어 있기 때문에

총 걸리는 일수는 (V-B) / (A-B) 이 될 것이다.

 

여기서 나누어 떨어지지 않고, 5.3 이런식으로 걸리게 된다면 5일안에는 도달을 못하기 때문에 올림을 하여 6이 된다.

import math
a, b, v = map(int, input().split())

answer = math.ceil((v-b) / (a-b))

print(answer)

 

https://github.com/HongEunho

 

HongEunho - Overview

📖 Android, Java, Kotlin, Algorithm. HongEunho has 15 repositories available. Follow their code on GitHub.

github.com

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

www.acmicpc.net/problem/1193

 

1193번: 분수찾기

첫째 줄에 X(1 ≤ X ≤ 10,000,000)가 주어진다.

www.acmicpc.net

문제 설명

문제에서, 나열된 분수들을 지그재그 순서로 찾아간다고 했는데, 이 재그재그를 설명하는 예시가 부족해 보였다.

그래서 초반에 이 지그재그 규칙을 찾아내느라 시간을 많이 썼던 것 같다.

 

X가 주어지면 X번째 분수를 출력하면 된다. ( 5번째 분수는 2/2 )


풀이 과정

위의 그림을 보면 일정한 규칙이 나타남을 알 수 있다.

라인에 있는 분수의 개수는 1라인은 1개, 2라인은 2개, 3라인은 3개, 4라인은 4개...

이런 식으로 늘어감을 알 수 있다.

 

짝수라인은 시작점에서 끝점으로 갈수록 분자가 1씩 늘어가고 분모가 1씩 감소하며

홀수라인은 시작점에서 끝점으로 갈수록 분자가 1씩 줄어들고 분모가 1씩 늘어난다.

 

그래서 내가 구하고자 하는 수가 몇번째 라인에 있는지, 그 중에서 몇 번째 인덱스에 있는지를 알면 된다.

 

여기서 end는 그 라인의 마지막 인덱스를 뜻한다. ( 1, 3, 6, 10 ... )

그래서 내가 구하고자 하는 인덱스까지 도달할동안 line과 end를 규칙에 따라 늘려가면 쉽게 찾을 수 있을 것이다.

n = int(input())

line = 0
end = 0
while n > end:
    line += 1
    end += line

diff = end - n
if line%2 == 0: #짝수 라인 일때
    top = line - diff
    bottom = diff + 1
else:
    top = diff + 1
    bottom = line - diff

print("%d/%d"%(top,bottom))

 

https://github.com/HongEunho

 

HongEunho - Overview

📖 Android, Java, Kotlin, Algorithm. HongEunho has 15 repositories available. Follow their code on GitHub.

github.com

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

www.acmicpc.net/problem/5212

 

5212번: 지구 온난화

첫째 줄에 지도의 크기 R과 C (1 ≤ R, C ≤ 10)가 주어진다. 다음 R개 줄에는 현재 지도가 주어진다.

www.acmicpc.net

문제 설명

지도 크기 N x M을 입력받은 후에 각각의 좌표 칸 바다(.) 인지 땅(X)인지를 입력한다.

이 때, 50년 후의 섬 주변( 상, 하, 좌, 우) 으로 3개 이상의 바다가 존재한다면 그 땅은 바다로 변하게 된다.

또한 바다만 있는 줄이나 칸은 모두 사라진다. ( 맵의 바깥쪽은 모두 바다이기 때문에 바다만 있는 줄, 칸은 생략된다)

따라서 50년 후에는 당연히 맵의 크기는 줄어들 것이다.

이 때, 50년 후의 지도를 출력하면 된다.

위의 예제로 예를 들면, (3,0)의 X는 위, 왼쪽, 아래가 모두 바다이기 때문에 .으로 변하게 된다.

또한, X=0 ( 첫 번째 줄)은 모두 바다이기 때문에 아예 없애준다.


풀이 과정

이 문제는 구현(Implementation) 문제이다.

각 칸마다 DFS / BFS 검사를 하듯이 상하좌우로 검사를 해준다. ( 범위를 벗어나면 오류가 나므로 범위 지정은 필수 )

 

new_graph가 변환 후의 맵인데, deepcopy를 해준 이유는 그냥 복사(=)를 하게 되면 한 맵을 수정하게 되면 두 맵이 같이 바뀌게 된다. 따라서 deepcopy를 해주어 기존 비교용 맵과 새로 바꿀용 맵을 바꾸어 준 것이다.

 

현재 땅을 기준으로 상하좌우에 바다가 3칸 이상 존재하면 현재 땅을 바다로 만들어 준다.

그리고 첫 번째 X가 나타나는 줄을 start_row, 마지막 X가 나타나는 줄을 end_row로 지정하여

줄여진 맵의 행수를 정해주며

마찬가지로 칸 수도 같은 방식으로 진행하여, 줄여진 맵의 열의 수를 정해준다.

import copy
r, c = map(int, input().split())

graph = []
for i in range(r):
    graph.append(list(input()))
new_graph = copy.deepcopy(graph)

dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

for x in range(r):
    for y in range(c):
        if graph[x][y] == '.':
            continue
        sea_count = 0
        for k in range(4):
            nx = x + dx[k]
            ny = y + dy[k]
            if nx < 0 or nx >= r or ny < 0 or ny >= c:
                sea_count += 1
                continue
            elif graph[nx][ny] == '.':
                sea_count += 1

        if sea_count >= 3:
            new_graph[x][y] = '.'

start_row = 0
start_col = 0
end_row = 0
end_col = 0
min_index = c-1
max_index = 0

for i in range(r):
    if 'X' in new_graph[i]:
        start_row = i
        break

for i in range(r-1, -1, -1):
    if 'X' in new_graph[i]:
        end_row = i
        break

for i in range(start_row,  end_row+1):
    tmp = [i for i, value in enumerate(new_graph[i]) if value == 'X']
    if not tmp:
        continue
    min_tmp = tmp[0]
    max_tmp = tmp[-1]
    min_index = min(min_index, min_tmp)
    max_index = max(max_index, max_tmp)

for i in range(start_row, end_row+1):
    for j in range(min_index, max_index+1):
        print(new_graph[i][j], end='')
    print()

마지막 쯤에 tmp = [i for i, value in enumerate(new_graph[i]) if value == 'X'] 부분이 헷갈릴 수 있는데,

enumerate는 컬렉션의 원소를 ( 인덱스, 원소값 ) 으로 반환해주는 함수라고 생각하면 된다. 

즉 여기서는 (i, value) 형태로 반환하는데 나는 인덱스만 필요하기 때문에 i만 tmp 리스트에 넣으면 된다.

그래서 칸(열)의 최소값과 최댓값을 구해 맵의 열 수를 구하면 되는 것이다.

 

https://github.com/HongEunho

 

HongEunho - Overview

📖 Android, Java, Kotlin, Algorithm. HongEunho has 15 repositories available. Follow their code on GitHub.

github.com

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

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

 

3107번: IPv6

첫째 줄에 올바른 IPv6 주소가 주어진다. 이 주소는 최대 39글자이다. 또한, 주소는 숫자 0-9, 알파벳 소문자 a-f, 콜론 :으로만 이루어져 있다.

www.acmicpc.net

문제 설명

IPv6의 주소는 32자리의 16진수를 4자리씩 끊어 나타낸다. 이때, 각 그룹은 콜론 (:)으로 구분해서 나타낸다.

예를 들면, 2001:0db8:85a3:0000:0000:8a2e:0370:7334 이런 식으로 나타낸다.

 

 

문제에서는, 규칙 두가지가 존재한다.

1. 각 그룹의 앞자리의 0의 전체 또는 일부를 생략 할 수 있다. 위의 IPv6을 축약하면, 다음과 같다

2001:db8:85a3:0:00:8a2e:370:7334

 

2. 만약 0으로만 이루어져 있는 그룹이 있을 경우 그 중 한 개 이상 연속된 그룹을 하나 골라 콜론 2개(::)로 바꿀 수 있다.

2001:db8:85a3::8a2e:370:7334

 

2번째 규칙은 모호함을 방지하기 위해서 오직 한 번만 사용할 수 있다.

올바른 축약형 IPv6주소가 주어졌을 때, 이를 원래 IPv6 (32자리의 16진수)로 복원하는 프로그램을 작성해야 한다.

 

예를 들어, 25:09:1985:aa:091:4846:374:bb 라는 입력이 주어졌을 때,

0025:0009:1985:00aa:0091:4846:0374:00bb 이런 식으로 복구하여 출력을 하면 된다.


풀이 과정

1) 입력 문자열을 ":"를 기준으로 나눠 리스트에 담는다. (ip 배열)

2) 각 칸이 4글자이면 복구 전과 후가 같으므로 그대로 옮긴다.

3) 0보다 크고 4글자 보다 작으면 0의 일부만 생략된 것이므로 그 수만큼 0을 추가한다.

4) 0글자이면 경우의 수가 두가지 이다.

    4-1) 문제에서 말한 두 번째 규칙인 연속된 그룹들이 생략된 경우

          -> 남은 칸 수( 8 - len(ip) ) 들을 모두 0으로 채운다.

    4-2) 한 그룹만 생략된 경우

          -> 해당 칸만 0으로 모두 채운다.

 

위의 과정의 소스 코드는 다음과 같다.

ip = list(input().split(":"))

index = 0
ans = ['' for _ in range(8)]
flag = 0

for i in range(len(ip)):
    if len(ip[i]) == 4:
        ans[index] = ip[i]
        index += 1

    elif len(ip[i]) > 0:
        ans[index] = '0' * (4 - len(ip[i])) + ip[i]
        index += 1

    else: # len(ip[i]) == 0
        if flag == 0:
            for j in range(8 - len(ip) + 1):
                ans[index] = '0000'
                index += 1
            flag = 1
        else:
            ans[index] = '0000'
            index += 1

for i in range(len(ans)-1):
    print(ans[i], end=':')

print(ans[-1])

https://github.com/HongEunho

 

HongEunho - Overview

📖 Android, Java, Kotlin, Algorithm. HongEunho has 15 repositories available. Follow their code on GitHub.

github.com

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

 

 

반응형
반응형

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

 

14500번: 테트로미노

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다. 정사각형은 서로 겹치면 안 된다. 도형은 모두 연결되어 있어야 한다. 정사각형의 변

www.acmicpc.net

문제 설명

링크에서 알 수 있듯이,

좌표 크기 N x M을 입력받은 후에 각각의 좌표 칸 마다 숫자를 부여한다.

 

그리고 우리가 흔히 해봤던 테트리스 게임의 블록 모양들을 이 좌표 위에 올려놓게 되는데

블록이 위치하는 좌표의 숫자들의 합이 최대가 되는 값을 구하면 된다.

즉, 내가 ㅡ(일자 막대) 모양의 블록을 (0,0) (0,1), (0,2), (0,3) 좌표 위에 올려놓았다면

이 네 좌표의 숫자 값을 모두 더해 저장해놓은 후에 이러한 값들의 최댓값을 구하면 되는 것이다.

 


풀이 과정

이 문제는 브루트 포스(Brute-Force) 유형의 구현 문제이다.

모든 칸에 대해 검사를 해보아야 한다.

문제에서 주어진 맵의 크기가 상대적으로 작기 때문에 (4 ≤ N, M ≤ 500)

모든 블록을 모든 칸에 대해 검사하는 방법으로 해결하였다.

 

1. 모든 블록 모양을 각각의 함수로 만든다.

2. 모든 좌표 칸 마다 각각의 함수들의 결과값을 구해 최댓값을 구한다.

 

이 방법 외에도, 모든 블록모양을 담을 수 있는 큰 크기의 2차원 배열을 선언하여

2차원 배열안에 0과 1로 블록 모양을 지정해주는 방식도 있다.

 

편한 방법으로 문제를 해결하면 될 것 같다.

 

코드는 다음과 같다.

n, m = map(int,input().split())
graph = []
ans = 0

def shape1(i, j): # ㅡ
    if j+3 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i][j+2] + graph[i][j+3]

def shape2(i, j): # ㅣ
    if i+3 >= n:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+2][j] + graph[i+3][j]

def shape3(i, j): # L모양
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+2][j] + graph[i+2][j+1]

def shape4(i, j): # L모양 대칭
    if i+2 >= n or j-1 < 0:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+2][j] + graph[i+2][j-1]

def shape5(i, j): # L모양 시계방향 회전
    if i-1 < 0 or j+2 >= m:
        return 0
    return graph[i][j] + graph[i-1][j] + graph[i-1][j+1] + graph[i-1][j+2]

def shape6(i, j): # L대칭 시계방향 회전
    if i+1 >= n or j+2 >=m:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j+1] + graph[i+1][j+2]

def shape7(i, j): # L 시계방향 회전x2
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j+1] + graph[i+2][j+1]

def shape8(i, j): # L대칭 시계방향 회전x2
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j] + graph[i+2][j]

def shape9(i, j): # L 시계방향 회전x3
    if i-1 < 0 or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i][j+2] + graph[i-1][j+2]

def shape10(i, j): # L대칭 시계방향 회전x3
    if i+1 >= n or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i][j+2] + graph[i+1][j+2]

def shape11(i, j): # ㅁ모양
    if i+1 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j] + graph[i+1][j+1]

def shape12(i, j): # 번개모양
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j+1] + graph[i+2][j+1]

def shape13(i, j): # 번개모양 회전
    if i-1 < 0 or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i-1][j+1] + graph[i-1][j+2]

def shape14(i, j): #번개모양 대칭
    if i+2 >= n or j-1 < 0:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j-1] + graph[i+2][j-1]

def shape15(i, j): #번개모양 대칭 회전
    if i+1 >= n or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j+1] + graph[i+1][j+2]

def shape16(i, j): #ㅗ모양
    if i-1 < 0 or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i-1][j+1] + graph[i][j+2]

def shape17(i, j): #ㅗ모양 회전
    if i+2 >= n or j+1 >= m:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j+1] + graph[i+2][j]

def shape18(i, j): #ㅗ모양 회전x2
    if i+1 >= n or j+2 >= m:
        return 0
    return graph[i][j] + graph[i][j+1] + graph[i+1][j+1] + graph[i][j+2]

def shape19(i, j): #ㅗ모양 회전x3
    if i+2 >= n or j-1 < 0:
        return 0
    return graph[i][j] + graph[i+1][j] + graph[i+1][j-1] + graph[i+2][j]


for i in range(n):
    graph.append(list(map(int,input().split())))

for i in range(n):
    for j in range(m):
        ans = max(ans, shape1(i,j), shape2(i,j), shape3(i,j), shape4(i,j), shape5(i,j), shape6(i,j), shape7(i,j), shape8(i,j), shape9(i,j),
                  shape10(i,j), shape11(i,j), shape12(i,j), shape13(i,j), shape14(i,j), shape15(i,j), shape16(i,j), shape17(i,j), shape18(i,j), shape19(i,j))

print(ans)

 

 

 

 

https://github.com/HongEunho

 

HongEunho - Overview

📖 Android, Java, Kotlin, Algorithm. HongEunho has 15 repositories available. Follow their code on GitHub.

github.com

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

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

 

8911번: 거북이

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 컨트롤 프로그램이 주어진다. 프로그램은 항상 문제의 설명에 나와있는 네가지 명령으로만 이루어져

www.acmicpc.net

거북이 로봇이 좌표 ( 0, 0 ) 을 시작으로 움직인다. 알파벳으로 명령을 하게 되는데,

  • F: 한 눈금 앞으로
  • B: 한 눈금 뒤로
  • L: 왼쪽으로 90도 회전
  • R: 오른쪽으로 90도 회전 이다.

주의할 점은, L과 R 명령일 때는 움직이지 않고 현재 내 좌표에서 방향만 바꾸는 것이다.

 

각각의 케이스에 대하여, 거북이의 이동좌표를 모두 포함하는 가장 작은 직사각형의 넓이를 출력하면 된다.

즉, (0,0) -> (0,1) -> (0,2) -> (1,2) 로 이동하였다면 정답은 2가 되는 것이다.

 

이 문제는 문제를 보며 해결 과정을 하나씩 발견해가며 그 과정을 소스코드로 바꾸는 '구현(Implementation)' 유형이다.

 

코드는 다음과 같다.

n = int(input())

dx = [0,-1,0,1]
dy = [1,0,-1,0] # 북 서 남 동

for i in range(n):
    pos_x = 0
    pos_y = 0
    pos_dir = 0  # 0북 1서 2남 3동
    move = list(input())
    trace = [(pos_x, pos_y)]
    for j in move:
        if j == 'F':
            pos_x = pos_x + dx[pos_dir]
            pos_y = pos_y + dy[pos_dir]
        elif j == 'B':
            pos_x = pos_x - dx[pos_dir]
            pos_y = pos_y - dy[pos_dir]
        elif j == 'L':
            if pos_dir == 3:
                pos_dir = 0
            else:
                pos_dir += 1
        elif j == 'R':
            if pos_dir == 0:
                pos_dir = 3
            else:
                pos_dir -= 1

        trace.append((pos_x, pos_y))
    width = max(trace, key = lambda x:x[0])[0] - min(trace, key = lambda x:x[0])[0]
    height = max(trace, key = lambda x:x[1])[1] - min(trace, key = lambda x:x[1])[1]
    print(width * height)


궁금한 점이 있으면 언제든지 댓글 남겨주세요

 

https://github.com/HongEunho

 

HongEunho - Overview

📖 Android, Java, Kotlin, Algorithm. HongEunho has 15 repositories available. Follow their code on GitHub.

github.com

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형
반응형

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

 

3020번: 개똥벌레

개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항상 석순이고, 그 다음에는 종유석과 석순이

www.acmicpc.net

지난번에 이분탐색(Binary Search)으로 풀었던 개똥벌레 문제

https://hongcoding.tistory.com/5

 

[백준] 3020번 개똥벌레 (Python 파이썬)

https://www.acmicpc.net/problem/3020 3020번: 개똥벌레 개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항

hongcoding.tistory.com

이 문제를 누적합 (전위합(Prefix Sum)) 으로 다시 풀었다.

높이 h부터 높이 1까지 누적 합을 계산하면 높이 i의 배열 값은 높이 i 이상의 모든 석순의 개수가 된다.

예를 들어, 높이가 6인 동굴에서 높이 5의 개똥벌레가 날아갈 때, 높이 5 이상의 석순에 모두 부딪히기 때문에

배열 5의 값이 높이 5의 개똥벌레가 부딪히는 석순의 개수가 된다.

 

마찬가지로 종유석은 위에서부터 내려오기 때문에 h - i + 1의 식을 이용하면 된다.

왜냐하면, 높이 6의 동굴에서 높이 2짜리 종유석은 높이 4 (실질적으로 3.5) 위로의 개똥벌레가 모두 부딪히기 때문이다.

즉, 석순처럼 높이2라고 해서 높이 2 밑의 개똥벌레가 부딪히는것이 아니라 위에서 부터기 때문에 반대가 된다.

 

파이썬 코드는 다음과 같다.

n, h = map(int, input().split())

down = [0] * (h + 1)  # 석순
up = [0] * (h + 1)  # 종유석

min_count = n  # 파괴해야 하는 장애물의 최소값
range_count = 0  # 최소값이 나타나는 구간의 수

for i in range(n):
    if i % 2 == 0:
        down[int(input())] += 1
    else:
        up[int(input())] += 1

for i in range(h - 1, 0, -1):
    down[i] += down[i + 1]
    up[i] += up[i + 1]

for i in range(1, h + 1):

    if min_count > (down[i] + up[h - i + 1]):
        min_count = (down[i] + up[h - i + 1])
        range_count = 1
    elif min_count == (down[i] + up[h - i + 1]):
        range_count += 1

print(min_count, range_count)

모르시는 부분이 있으시면 언제든지 댓글 남겨주세요!

 

https://github.com/HongEunho

 

HongEunho - Overview

📖 Android, Java, Kotlin, Algorithm. HongEunho has 15 repositories available. Follow their code on GitHub.

github.com

전체 문제 & 코드는 위의 깃에 정리되어 있습니다.

팔로우 & 맞팔은 환영입니다 !

반응형

+ Recent posts