[Programmers] 조이스틱 -Python3

문제분석

1. 관찰
- "A"*len(name) 상태에서 주어진 name을 만들기위해 조이스틱을 상하좌우로 움직이는 최소 횟수를 구해야한다.
- 상하로 움직이는 경우는 각 자리의 문자와 "A"의 유니코드 정수의 차이를 사용하여 최소 횟수를 구할 수 있다.
- 하지만, 좌우로 이동하는 경우는 A의 유무, A의 연속된 길이, A의 위치에 따라 움직임을 고려해 주어야 하기 때문에 이를 고려하여 최소 움직임을 구해야한다.

- 다른 풀이들을 참고하였지만, 좌측으로 움직임, 우측으로 움직임을 수식으로 정리하여 최소 값을 구하는 방식이 직관적으로 이해가 되지 않았다.
- 따라서, 좌우 이동의 최소횟수를 구하기 위해서 최단거리를 구하는데 일반적으로 사용되는 BFS 알고리즘으로 접근하였다.

-  "A"*len(name)에서 주어진 name을 만들기 위해 A가 아닌 곳을 바꾸기위해 최소로 움직이며 모두 방문하여 주어진 name과 일치하도록 만들어주어야한다.
- 역으로, 주어진 name이 모두 A가 되게하는 최소 이동거리를 구해준다.

- name이 "A"*len(name)이 될 때까지 BFS를 해주며 좌우로 이동한 거리를 누적해준다.
- 이때, "A"*len(name)을 가장 빨리 만족하는 경우를 찾기위해 deque에 현재 name 의 상태를 deepcopy하여 기록해나가야한다.

2. 복잡도
- O(len(name) + len(name)) = 20 + 20 = 40
- 검토 필요

3. 자료구조
- 이름: str[]
- BFS: deque

해결코드

from collections import deque

def bfs(name):
    q = deque([(list(name), 0, 0)])

    while q:
        name_list, lr_cnt, idx = q.popleft()
        name_list[idx]='A'

        if name_list.count('A') == len(name):
            return lr_cnt

        for i in [-1,1]:
            name_copy = name_list[:]
            q.append((name_copy, lr_cnt+1, idx+i))

def solution(name):
    up_cnt = sum([min(abs(ord('A')-ord(n)), 26-abs(ord('A')-ord(n))) for n in name])
    lr_cnt = bfs(name)
    return up_cnt + lr_cnt

[Programmers] 전력망을 둘로 나누기 -Python3

문제분석

1. 관찰
- 송전탑이 전선을 통해 하나의 트리(Tree) 형태로 연결되어 있다.
- 따라서 송전탑은 '노드', 전선은 '간선'으로 이해할 수 있다.

- 문제에서 요구하기를 전력망 네트워크를 2개로 분할하려고 한다.
- 주어진 간선의 개수가 99개 이하임으로 완전 탐색을 구현해도 된다.
  - wires 중 하나를 제거하면 네트워크가 2개로 분할되는 것을 이용해 완전 탐색을 한다.

- 2개로 분할된 모든 경우에 대하여 두 네트워크의 노드 개수를 비교하고 최소값을 출력한다.
  - 분할된 한 네트워크에 대하여 BFS하여 노드의 개수를 구한다.
  - 전체 노드의 개수 n을 사용하여 두 네트워크의 노드의 개수를 비교한다.

2. 복잡도
- O(V*(V+E)) =  99 * (99 + 100)  => 그냥 가능이다.
- 합리적으로 완전탐색을 시도할 수 있다.

3. 자료구조
- 트리: int[][]
- 방문 처리: int[]

해결코드

from collections import deque

def bfs(tree, start, visited):
    q = deque([start])
    visited.append(start)
    while q:
        now = q.popleft()
        for nxt in tree[now]:
            if nxt not in visited:
                q.append(nxt)
                visited.append(nxt)
    return len(visited)

def solution(n, wires):

    answer = n

    for i in range(len(wires)):
        tree = [[] for _ in range(n)]
        for idx, wire in enumerate(wires):
            if idx==i:
                continue
            tree[wire[0]-1].append(wire[1]-1)
            tree[wire[1]-1].append(wire[0]-1)

        one = bfs(tree, 0, [])

        result = abs((n - one) - one)

        if answer > result:
            answer = result

    return answer

'Etc > PS' 카테고리의 다른 글

[Programmers] 조이스틱 -Python3  (0) 2022.10.11
[Programmers] 징검다리 -Python3  (0) 2022.10.11
[Programmers] 입국심사 python3  (0) 2022.09.30
[Programmers] 모음사전 python3  (0) 2022.09.30
[Kakao] 광고 삽입 Python3  (0) 2022.09.29

2178 미로 탐색

문제 분석

1.  아이디어
-   최단거리 탐색 문제
-   BFS는 현재 노드에서 가까운 곳부터 찾기 때문에 경로 탐색 시 첫번째로 찾아지는 해답이 최단거리임을 보장
-   상하좌우 모두 탐색
-   상하좌우 좌표가 미로의 범위 밖 or 0이면 탈락

2.  복잡도
-   상하좌우 BFS O(n)

3.  자료구조
-   리스트, 큐

해결코드

import sys
from collections import deque
input = sys.stdin.readline

n, m = map(int, input().split())    # n줄, 길이 m짜리 입력
maze = list(list(map(int,' '.join(input()).split())) for _ in range(n))    # ' '.join(input()) 입력된 문자열을 ' '간격을 하나의 문자열로 반환

# 이동
dx = [-1,1,0,0]
dy = [0,0,-1,1]

q = deque([(0,0)])
result = 0

while q:
    x,y=q.popleft()
    for i in range(4):    # 상하좌우 방문
        nx,ny=x+dx[i],y+dy[i]
        if 0<=nx<n and 0<=ny<m:    # 미로의 범위내에 있고
            if maze[nx][ny]==1:    # 다음이 1이라면
                #방문처리
                maze[nx][ny]=maze[x][y]+1    # 탐색하면서 미로에 이동거리 업데이트
                q.append((nx,ny))    # 방문 노드
print(maze[n-1][m-1])   # 도착 좌표 이동거리 출력

'Etc > PS' 카테고리의 다른 글

BOJ_10870 피보나치 수 5 - Python3  (0) 2022.07.20
BOJ_10026 적록색약 - Python3  (1) 2022.07.14
BOJ_11279 최대 힙 - Python3  (1) 2022.07.11
BOJ_1927 최소 힙 - Python3  (0) 2022.07.11
BOJ_1996 프린터 큐 - Python3  (0) 2022.07.08

그래프

여러 개체들이 연결되어 있는 자료구조

탐색

특정 개체를 찾기 위한 알고리즘

대표적 문제 유형

  1. 경로탐색 유형 (최단거리, 시간)
  2. 네트워크 유형 (연결)
  3. 조합 유형 (모든 조합 만들기)

 

DFS(Depth-Firsh Search) 깊이 우선 탐색

  • 한 놈만 끝까지 패는 유형

구현 방법

  • 재귀함수가 가장 일반적
  • 한 가지 방법을 끝까지 다 해보고 다음 방식 동작

 

BFS(Breadth-First Search) 너비 우선 탐색

  • 여러 놈을 한대씩 때리면서 가는 유형

구현 방법

  • Queue / LinkedList 사용이 가장 보편적

 

DFS/BFS 알고리즘 판단 방법

  • 자신있는 알고리즘으로 탐색
  • DFS의 장점: 하나의 조합을 완성해서 정답과 비교하는 방식임으로 동작 검증이 쉽다
  • BFS의 장점: 시간복잡도가 낮다(효율성 TC에 유리)

 

참조

'CS > DSA' 카테고리의 다른 글

[자료구조] Array (배열) & LinkedList (연결리스트)  (0) 2022.08.01

+ Recent posts