18430_[문제이름] (Python)

0. 출처

1. 기록

  • 22/04/11 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 특정 3칸을 차지하면 나머지 칸에서 ㄱ or ㄴ 형태로 3칸을 차지하는 모든 경우를 체크해서 
>> 문제에서 요구하는 사항에 맞는 최댓값을 갱신시킨다.
>> 특정 3칸을 이동하고 다시 반복
>> 특정 3칸 ㄱ or ㄴ 형태를 어떻게 입력시킬 것인지?
>> ┌, ┐, └, ┘ 각 4가지 모양을 기준으로 위의 로직을 반복한다.

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
3 3
32 83 75
24 96 56
71 88 12

- 예제 출력 1 -
632

- 예제 입력 2 -
1 1
7

- 예제 출력 2 -
0

(3) 코드

# (0,0)부터 시작
# 시작점을 방문안했으면
#   부메랑 블럭이 범위 안에 있고, 방문안했으면 --> 강도 계산
# 시작점을 방문했으면
#   시작점 = 한칸 옆
def first(y, x):
    return woods[y][x-1] + 2*woods[y][x] + woods[y-1][x]


def second(y, x):
    return woods[y][x-1] + 2*woods[y][x] + woods[y+1][x]


def third(y, x):
    return woods[y+1][x] + 2*woods[y][x] + woods[y][x+1]


def fourth(y, x):
    return woods[y-1][x] + 2*woods[y][x] + woods[y][x+1]


def solve(y, x, strength):
    global N, M, answer
    if x == M:
        x = 0
        y += 1
    if y == N:
        answer = max(answer, strength)
        return
    if not visited[y][x]:
        if y - 1 >= 0 and x - 1 >= 0 and not visited[y][x-1] and not visited[y-1][x]:
            visited[y][x] = visited[y][x-1] = visited[y-1][x] = True
            this_strength = strength + first(y, x)
            solve(y, x+1, this_strength)
            visited[y][x] = visited[y][x-1] = visited[y-1][x] = False
        if y + 1 < N and x - 1 >= 0 and not visited[y+1][x] and not visited[y][x-1]:
            visited[y][x] = visited[y][x-1] = visited[y+1][x] = True
            this_strength = strength + second(y, x)
            solve(y, x+1, this_strength)
            visited[y][x] = visited[y][x-1] = visited[y+1][x] = False
        if y + 1 < N and x + 1 < M and not visited[y+1][x] and not visited[y][x+1]:
            visited[y][x] = visited[y][x+1] = visited[y+1][x] = True
            this_strength = strength + third(y, x)
            solve(y, x+1, this_strength)
            visited[y][x] = visited[y][x+1] = visited[y+1][x] = False
        if y - 1 >= 0 and x + 1 < M and not visited[y-1][x] and not visited[y][x+1]:
            visited[y][x] = visited[y][x+1] = visited[y-1][x] = True
            this_strength = strength + fourth(y, x)
            solve(y, x+1, this_strength)
            visited[y][x] = visited[y][x+1] = visited[y-1][x] = False
    solve(y, x+1, strength)


N, M = map(int, input().split())
woods = [list(map(int, input().split())) for _ in range(N)]
visited = [[False] * M for _ in range(N)]
answer = 0
solve(0, 0, 0)
print(answer)

(4) 정리

아이디어는 맞았으나 구현을 제대로 못해 해답을 찾아본 문제입니다.
구체적으로 visited 등에 ┌, ┐, └, ┘등 각 모양을 체크 후 재귀를 구현하는걸 세세히 코드화시키지 못하였습니다.
구현력 기르는 연습을 계속해야할 듯 합니다.

(5) 참고

참고 풀이1
참고 풀이2
참고 풀이3

1174__줄어드는 수 (Python)

0. 출처

1. 기록

  • 22/04/10 (일)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 예제 입력과 예제 출력을 보고 뭔말인지 도저히 모르겠음
>> 문제 이해 함
>> 문제 조건에 맞는 1번째로 가장 작은수는 0
>> 2번째로 가장 작은 수는 1
>> 3번째로 가장 작은 수는 2
>> ...
>> 10번째로 가장 작은 수는 9
>> 11번째로 가장 작은 수는 10
>> 12번째로 가장 작은 수는 20

>> 그래서 어떻게 풀건데? 
>> 마지막 값 > 현재 값 경우, 재귀 진행하여 감소하는 수를 만들어 준다.
>> 감소하는 수를 정렬한다.

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
sample

- 예제 출력 1 -
sample

(3) 코드

n = input()
arr = list()
result = list()

def dfs():
    if len(arr) > 0:
        result.append(int("".join(map(str, arr))))

    for i in range(0, 10):
        if len(arr) == 0 or arr[-1] > i:  # 마지막 값이 더 큰 경우
            arr.append(i)
            print(arr)
            dfs()
            arr.pop()

try:
    dfs()
    result.sort()
    print(result[n - 1])
except:
    print(-1)

(4) 정리

처음에 문제가 이해가 안가서 답안 코드에 1부터 하나하나 집어넣고 이해했다.

문제 이해력을 길러야겠다.

(5) 참고

참고 풀이

16235_나무 재테크 (Python)

0. 출처

1. 기록

  • 22/04/07 (목)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>>
>>

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
sample

- 예제 출력 1 -
sample

(3) 코드

sample

(4) 정리

(5) 참고

참고 풀이

15685_드래곤 커브 (Python)

0. 출처

1. 기록

  • 22/04/07 (목)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>>
>>

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
sample

- 예제 출력 1 -
sample

(3) 코드

sample

(4) 정리

0 세대 - 0

1 세대 - 0 1

2 세대 - 0 1 2 1

3 세대 - 0 1 2 1 2 3 2 1

4 세대 - 0 1 2 1 2 3 2 1 2 3 0 3 2 3 2 1

다음 세대는 이전 세대의 '역방향'으로 +1 한 방향을 나타내게 된다. (문제에서 핵심이 되는 규칙성★)
(사람들이 이러한 규칙성을 봤다는게 신기함..)

또한 세대가 증가할 때, 선분의 갯수가 공비가 2인 등비 수열인 것을 파악할 수 있다.
이것으로 배열의 크기를 추측 및 설정할 수 있다.

단순 이중 반복문을 통해 네 꼭짓점이 드래곤 커브로 만들어졌는지 확인하면 된다.
주의할 점은 x, y 방향으로 벽에 도달했을 때는 탐색할 수 없다는 것이다.

(5) 참고

문제 이해1
문제 이해2

14888_연산자 끼워넣기 (Python)

0. 출처

1. 기록

  • 22/04/03 (일)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>>
>>

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
sample

- 예제 출력 1 -
sample

(3) 코드

# 백트래킹 (Python3 통과, PyPy3도 통과)
import sys

N = int(input())
num = list(map(int, input().split()))
op = list(map(int, input().split()))  # +, -, *, //

maximum = -1e9
minimum = 1e9


def dfs(depth, total, plus, minus, multiply, divide):
    global maximum, minimum
    if depth == N:
        maximum = max(total, maximum)
        minimum = min(total, minimum)
        return

    if plus:
        dfs(depth + 1, total + num[depth], plus - 1, minus, multiply, divide)
    if minus:
        dfs(depth + 1, total - num[depth], plus, minus - 1, multiply, divide)
    if multiply:
        dfs(depth + 1, total * num[depth], plus, minus, multiply - 1, divide)
    if divide:
        dfs(depth + 1, int(total / num[depth]), plus, minus, multiply, divide - 1)


dfs(1, num[0], op[0], op[1], op[2], op[3])

print(maximum)
print(minimum)

(4) 정리

(5) 참고

참고 풀이

14712_넴모넴모 (Easy) (Python)

0. 출처

1. 기록

  • 22/04/04 (월)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
2 2

- 예제 출력 1 -
15

- 예제 입력 2 -
2 3

- 예제 출력 2 -
57

- 예제 입력 3 -
3 5

- 예제 출력 3 -
22077

(3) 코드

import sys

n, m = map(int, sys.stdin.readline().split())
graph = [[0] * (m + 1) for _ in range(n + 1)]
answer = 0


def dfs(cnt):
    global answer
    if cnt == n * m:
        answer += 1
        return

    x = cnt // m + 1
    y = cnt % m + 1

    dfs(cnt + 1)
    if graph[x - 1][y] == 0 or graph[x][y - 1] == 0 or graph[x - 1][y - 1] == 0:
        graph[x][y] = 1
        dfs(cnt + 1)
        graph[x][y] = 0


dfs(0)
print(answer)

(4) 정리



문제 가지수가 왜 저렇게 나오나 해서 직접 그려보았다.
넴모넴모가 없는 경우까지 count 해주면 출력값이랑 똑같이 나온다.

힌트를 나중에 봤는데 각 칸 별로 넴모가 있는 경우 없는 경우로 경우의 수를 계산하면
넴모가 4격자를 채우는 경우를 포함한 모든 경우를 좀 더 빨리 구할 수 있긴하다.
문제풀이 방식은 힌트를 기초하여 풀은 방식이다.

풀이 방법을 이해하는데 한참걸렸다.
우선 각 칸을 1로 차례차례 채우며 cnt를 증가시킨다.(넴모를 둔다는 의미)
만약 해당 칸에 넴모를 둬서 2x2 격자넴모가 완성되는 경우는 1을 두지 않고 0으로 남긴채로 cnt를 증가시킨다.
그리고 다시 나머지 칸을 채운다.
전체 격자 수만큼 cnt가 채워진 경우 answer를 1증가시킨다. (answer는 문제 조건에 맞게끔 칸이 채워진 경우를 의미)

# 2 x 3 의 격자의 경우 맨 처음에 이렇게 넴모가 채워진다.
# graph[1][1] 에 넴모(1)를 채우면 문제 조건에 만족하지 못하므로 이 경우는 건너뛰고 cnt만 증가시켜 진행한다.
1 1 1
1 0 1
# 그 다음 이런 식으로 graph[1][2]에 넴모를 제외한 식으로 확인하고
1 1 1
1 0 0
# 그 다음은 이렇게 graph[1][0] 에 넴모를 제외하고 그 뒤에 넴모를 채우는 방식으로
1 1 1
0 1 0

이렇게 해당 칸에 넴모를 넣는 경우와 빼는 경우를 문제에서 주어진 조건에 맞게끔 채우는 경우를 백트래킹 방식으로 반복한다.

(5) 참고

참고 풀이
이해잘되는 풀이

16987_계란으로 계란치기 (Python)

0. 출처

1. 기록

  • 22/04/03 (일)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>>
>>

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
3
8 5
1 100
3 5

- 예제 출력 1 -
3

- 예제 입력 2 -
3
1 100
8 5
3 5

- 예제 출력 2 -
2

- 예제 입력 3 -
1
123 45

- 예제 출력 3 -
0

- 예제 입력 4 -
8
222 117
176 92
287 6
284 81
221 96
263 96
188 40
225 1

- 예제 출력 4 -
4

- 예제 입력 5 -
6
65 281
272 145
233 175
229 12
99 88
142 159

- 예제 출력 5 -
6

(3) 코드

import sys

def check(eggs):
  count = 0
  for egg in eggs:
    if egg[0] <= 0:
      count += 1
  return count

def dfs(index, eggs):
  global answer

  if index == n:
    # 마지막 계란 까지 집은 경우
    answer = max(answer, check(eggs))
    return

  if eggs[index][0] <= 0:
    # 현재 계란의 내구도가 다 달았을 때 다음 계란으로 넘어간다.
    dfs(index + 1, eggs)

  else:
    # 현재 계란의 내구도가 남아있을 때 다른 계란들과 부딪친다. (현재 계란 제외, 내구도가 없는 계란 제외)
    is_all_broken = True
    for i in range(len(eggs)):
      if index != i and eggs[i][0] > 0:
        is_all_broken = False
        eggs[index][0] -= eggs[i][-1]
        eggs[i][0] -= eggs[index][-1]
        dfs(index + 1, eggs)
        eggs[index][0] += eggs[i][-1]
        eggs[i][0] += eggs[index][-1]

    # 모든 계란이 깨져있는 경우 dfs를 바로 빠져나와준다.
    if is_all_broken:
      dfs(n, eggs)

n = int(input())
eggs = []
answer = 0
for _ in range(n):
  eggs.append(list(map(int, input().split())))

dfs(0, eggs)
print(answer)

(4) 정리

예제 입력1 과 예제 입력2 의 결과가 왜 같은지 이해가 안되서 엄청 헤맸다.
처음에 모든 경우의 수로 다 쳐본다고 생각하고 시작했던게 이유였다.


  • 무조건 가장 왼쪽(처음)의 깨지지 않은 계란을 먼저 들고 계란 치는 행위를 시작한다.(이때 어느걸 먼저 치던지 상관없다.)
  • 경우1) 들었던 계란이 깨진 경우 깨지지 않은 다음 계란을 들고 계란 치는 행위를 반복한다.
  • 경우2) 들었던 계란으로 다른 계란을 쳤는데 다른 계란이 깨지지 않은 경우 다음 계란을 들고 계란치는 행위를 반복한다.
  • 모든 계란이 깨진 경우 종료한다.
  • 마지막 계란을 들었을 경우도 종료한다.

(5) 참고

참고 풀이
이해가 쉬운 풀이

10971_외판원 순회2 (Python)

0. 출처

1. 기록

  • 22/04/03 (일)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

'''
1. 아이디어
>>
>>

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

예제 입력 1
4
0 10 15 20
5 0 9 10
6 13 0 12
8 8 9 0

예제 출력 1
35

(3) 코드

n = int(input())
nums = [list(map(int, input().split())) for _ in range(n)]

depth = 0
answer = 99999999
visited = []

def recursive_dfs(city, depth, sum_cost, start):
    global answer

    # 순회를 마친 경우
    if depth == n:
        answer = min(answer, sum_cost)
        return

    for target in range(0, n):
        # 시작 지점으로 중간에 가지않으며 
        # target 이 city 가 되는 경우를 제외하고 
        # target 이 방문하지 않은 곳인 경우이고
        # city 에서 target 으로 갈때 0인 경우를 제외
        if target != start and target != city and target not in visited and nums[city][target] != 0:
            visited.append(target)
            sum_cost += nums[city][target]
            recursive_dfs(target, depth+1, sum_cost, start)
            sum_cost -= nums[city][target]
            visited.pop()

        # 마지막으로 시작지점으로 되돌아가기만 하면 되는 경우
        # city 에서 start 으로 갈때 0인 경우를 제외
        elif depth == n-1 and target == start and nums[city][start] != 0:
            visited.append(start)
            sum_cost += nums[city][start]
            recursive_dfs(city, depth + 1, sum_cost, start)
            sum_cost -= nums[city][start]
            visited.pop()

for city in range(n):
    sum_cost = 0
    target = 0
    start = city
    recursive_dfs(city, depth, sum_cost, start)

print(answer)

(4) 정리

코드를 어떻게 쉽게 작성해야 하나 고민중..
변수명만 적절하게 작성해도 어떻게 동작하는지 쉽게 그려져서 변수명에 신경을 잘 써야겠다.

(5) 참고

참고 풀이
질문 답변

1182_부분수열의 합 (Python)

0. 출처

1. 기록

  • 22/04/03 (일)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 부분 수열을 구한다.
>> 부분 수열의 합을 구하고 만족하는 부분수열을 카운트한다.

2. 시간복잡도
>>

3. 자료구조
>>

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
5 0
-7 -3 -2 5 8

- 예제 출력 1 -
1

(3) 코드

n, s = map(int, input().split())
nums = list(map(int, input().split()))

result = []

def iterative_dfs(index, path):
    # 매번 결과 추가
    result.append(path)

    for i in range(index, len(nums)):
        path = path+[nums[i]]
        iterative_dfs(i+1, path)

iterative_dfs(0, [])

cnt = 0

for answer in result:
    if answer != [] and sum(answer) == s:
        # print(answer)
        cnt += 1

print(cnt)

(4) 정리

(5) 참고

알고리즘 인터뷰 Q37. 부분집합 문제를 참고하면 좋습니다.

15666_N과 M(12)(Python)

0. 출처

1. 기록

  • 22/04/03 (일)

2. 풀이

(1) 아이디어, 시간복잡도, 자료구조

1. 아이디어
>> 주어진 수에 '중복된 숫자가 있을 때' 중복조합을 구하는 문제
>> set 이용 중복된 수를 제거하고 중복조합을 구한다.

2. 시간복잡도
>>

3. 자료구조
>>
'''

(2) 예제 입력, 예제 출력

- 예제 입력 1 -
3 1
4 4 2

- 예제 출력 1 -
2
4

- 예제 입력 2 -
4 2
9 7 9 1

- 예제 출력 2 -
1 1
1 7
1 9
7 7
7 9
9 9

(3) 코드

n, m = map(int, input().split())
nums = list(map(int, input().split()))
nums = set(nums)
nums = list(nums)
nums = sorted(nums)

stack = []

def iterative_dfs(start):
    if len(stack) == m:
        print(*stack)
        return

    for i in range(start, len(nums)):
        stack.append(nums[i])
        iterative_dfs(i)
        stack.pop()

iterative_dfs(0)

(4) 정리

(5) 참고

+ Recent posts