문제:

풀이방법:

 숫자를 만난 순간부터 계속해서 숫자를 연속해서 탐지할 수 있도록 알고리즘을 구성해야 하고 따라서 DFS를 사용해서 해당 문제를 풀었다.

 maps를 탐색하다가 X가 아니고, 이전에 탐색한 곳이 아니라면 DFS를 수행하며, 연속된 영역을 탐색하는 동안 visited를 계속해서 갱신하도록 한다. 이와 같은 과정을 방문할 곳이 남아 있지 않을 때까지 수행하고, 각 영역의 넓이는 마지막에 정렬을 하도록 한다.(단, 정렬할 영역이 없다면 -1을 반환)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from collections import deque
dx = [-1010]
dy = [010-1]
 
def dfs(x, y, maps, visited):
    area = int(maps[x][y])
    queue = deque([(x,y)])
    while queue:
        x, y = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0<=nx<len(maps) and 0<=ny<len(maps[0]):
                if maps[nx][ny]!='X' and visited[nx][ny]==0:
                    area+=int(maps[nx][ny])
                    visited[nx][ny] = 1
                    queue.append((nx, ny))
    return area, visited
 
def solution(maps):
    visited = [[0 for _ in range(len(maps[0]))] for _ in range(len(maps))]
    answers = []
    for i in range(len(maps)):
        for j in range(len(maps[0])):
            if maps[i][j]!='X' and visited[i][j]==0:
                visited[i][j] = 1
                answer, visited = dfs(i, j, maps, visited)
                answers.append(answer)
 
    if len(answers):
        return sorted(answers)
    else:
        return [-1]
cs

문제링크:

https://school.programmers.co.kr/learn/courses/30/lessons/154540

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

문제:

한수는 캠프를 마치고 집에 돌아가려 한다. 한수는 현재 왼쪽 아래점에 있고 집은 오른쪽 위에 있다. 그리고 한수는 집에 돌아가는 방법이 다양하다. 단, 한수는 똑똑하여 한번 지나친 곳을 다시 방문하지는 않는다.

      cdef  ...f  ..ef  ..gh  cdeh  cdej  ...f 
      bT..  .T.e  .Td.  .Tfe  bTfg  bTfi  .Tde 
      a...  abcd  abc.  abcd  a...  a.gh  abc. 
거리 :  6     6     6     8     8    10    6

위 예제는 한수가 집에 돌아갈 수 있는 모든 경우를 나타낸 것이다. T로 표시된 부분은 가지 못하는 부분이다. 문제는 R x C 맵에 못가는 부분이 주어지고 거리 K가 주어지면 한수가 집까지도 도착하는 경우 중 거리가 K인 가짓수를 구하는 것이다.

입력:

첫 줄에 정수 R(1 ≤ R ≤ 5), C(1 ≤ C ≤ 5), K(1 ≤ K ≤ R×C)가 공백으로 구분되어 주어진다. 두 번째부터 R+1번째 줄까지는 R×C 맵의 정보를 나타내는 '.'과 'T'로 구성된 길이가 C인 문자열이 주어진다.

출력:

첫 줄에 거리가 K인 가짓수를 출력한다.

풀이방법:

 DFS를 사용해서 시작점에서 도착점까지 이동하고, 한 번의 이동마다 거리를 하나씩 늘린다. 도착점에 도달한 경우 거리가 K와 같다면 answer를 하나 증가시키고, 그렇지 않다면 다시 되돌아 오는 과정을 수행한다. '다시 되돌아 온다' 라는 행동을 하기 위해 visited 배열을 사용하고, 그 위치로 이동한 경우에는 해당 좌표의 값을 1로 바꾸고, 다시 되돌아 온 경우에는 0으로 다시 바꿔주도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
dx = [-10 , 10]
dy = [0-10 , 1]
 
from collections import deque
 
def dfs(x, y, count):
    global answer
    visited[x][y]=1
    if [x,y]==[0, C-1]:
        if count==K:
            answer+=1
        return
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0<= nx < R and 0 <= ny < C  and visited[nx][ny]==0 and maps[nx][ny]!='T':
            visited[nx][ny]=1
            dfs(nx,ny,count+1)
            visited[nx][ny]=0
            
R, C, K = map(int,input().split())
maps = [list(input()) for _ in range(R)]
visited = [[0 for _ in range(C)] for _ in range(R)]
answer= 0
dfs(R-101)
print(answer)
cs

문제링크:

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

 

1189번: 컴백홈

첫 줄에 정수 R(1 ≤ R ≤ 5), C(1 ≤ C ≤ 5), K(1 ≤ K ≤ R×C)가 공백으로 구분되어 주어진다. 두 번째부터 R+1번째 줄까지는 R×C 맵의 정보를 나타내는 '.'과 'T'로 구성된 길이가 C인 문자열이 주어진다

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]14497. 주난의 난(難)  (0) 2022.08.16
[BOJ]12851. 숨바꼭질 2  (0) 2022.08.09
[BOJ]12869.뮤탈리스크  (0) 2022.08.02
[BOJ]2852. NBA 농구  (0) 2022.07.28
[BOJ]3474. 교수가 된 현우  (0) 2022.07.26

문제:

수빈이가 세상에서 가장 좋아하는 것은 소수이고, 취미는 소수를 가지고 노는 것이다. 요즘 수빈이가 가장 관심있어 하는 소수는 7331이다.

7331은 소수인데, 신기하게도 733도 소수이고, 73도 소수이고, 7도 소수이다. 즉, 왼쪽부터 1자리, 2자리, 3자리, 4자리 수 모두 소수이다! 수빈이는 이런 숫자를 신기한 소수라고 이름 붙였다.

수빈이는 N자리의 숫자 중에서 어떤 수들이 신기한 소수인지 궁금해졌다. N이 주어졌을 때, 수빈이를 위해 N자리 신기한 소수를 모두 찾아보자.

입력:

첫째 줄에 N(1 ≤ N ≤ 8)이 주어진다.

출력:

N자리 수 중에서 신기한 소수를 오름차순으로 정렬해서 한 줄에 하나씩 출력한다.

풀이방법:

 보통 일반적인 소수 문제의 경우에는 에라토스테네스의 체를 사용해서 소수인 수들을 모두 찾고 하는 것이 빠른 경우가 많으나, 이 문제의 경우에는 N = 8 인 경우에 수가 엄청 커지게 되고, 시간이 오래 걸리게 된다.

 따라서 이 문제의 경우에는 dfs를 사용해서 한자리씩 붙여 나가면서 소수를 판정하는 방식을 사용하도록 한다. 문제의 특징으로 인해 75가 소수가 아니므로, 그 뒤는 판정할 필요가 없기 때문이다. dfs의 종료 조건은 숫자의 길이가 N이 될 때까지 진행한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def check_prime(n):
    if n==1 or n==0:
        return 0
    for i in range(2int(n**0.5)+1):
        if n%i==0:
            return 0
    return 1
 
def dfs(number, length):
    if length==n:
        print(number)
        return
    for i in range(10):
        tmp = number+str(i)
        if check_prime(int(tmp)):
            dfs(tmp,length+1)
    
 
= int(input())
 
dfs('',0)
cs

문제링크:

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

 

2023번: 신기한 소수

수빈이가 세상에서 가장 좋아하는 것은 소수이고, 취미는 소수를 가지고 노는 것이다. 요즘 수빈이가 가장 관심있어 하는 소수는 7331이다. 7331은 소수인데, 신기하게도 733도 소수이고, 73도 소수

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]9205. 맥주 마시면서 걸어가기  (0) 2022.04.05
[BOJ]1439. 뒤집기  (0) 2022.03.31
[BOJ]1052. 물병  (0) 2022.03.24
[BOJ]1004. 어린 왕자  (0) 2022.03.22
[BOJ]2252. 줄 세우기  (0) 2022.03.17

문제:

여행을 떠난 세준이는 지도를 하나 구하였다. 이 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 한 칸은 한 지점을 나타내는데 각 칸에는 그 지점의 높이가 쓰여 있으며, 각 지점 사이의 이동은 지도에서 상하좌우 이웃한 곳끼리만 가능하다.

현재 제일 왼쪽 위 칸이 나타내는 지점에 있는 세준이는 제일 오른쪽 아래 칸이 나타내는 지점으로 가려고 한다. 그런데 가능한 힘을 적게 들이고 싶어 항상 높이가 더 낮은 지점으로만 이동하여 목표 지점까지 가고자 한다. 위와 같은 지도에서는 다음과 같은 세 가지 경로가 가능하다.

지도가 주어질 때 이와 같이 제일 왼쪽 위 지점에서 출발하여 제일 오른쪽 아래 지점까지 항상 내리막길로만 이동하는 경로의 개수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에는 지도의 세로의 크기 M과 가로의 크기 N이 빈칸을 사이에 두고 주어진다. 이어 다음 M개 줄에 걸쳐 한 줄에 N개씩 위에서부터 차례로 각 지점의 높이가 빈 칸을 사이에 두고 주어진다. M과 N은 각각 500이하의 자연수이고, 각 지점의 높이는 10000이하의 자연수이다.

출력:

첫째 줄에 이동 가능한 경로의 수 H를 출력한다. 모든 입력에 대하여 H는 10억 이하의 음이 아닌 정수이다.

풀이방법:

dfs와 DP를 같이 사용해서 이 문제를 풀었다. 기본적인 방식은 dfs를 사용해서 조건에 맞게 이동을 하며 최종 목적지까지 탐색을 한다. 그러다가 최종 목적지에 도달하면 재귀를 빠져나오면서 그 경로에 +1을 해주면서 다시 돌아오게 된다. 

이 과정을 가능한 모든 경우에 대해서 수행할 수 있기 때문에 최종적으로는 dp[0][0]에 저장되어 있는 값을 출력해주면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import sys
 
sys.setrecursionlimit(10**6)
 
def dfs(x,y):
    if x==M-1 and y==N-1:
        return 1
    if dp[x][y] !=-1:
        return dp[x][y]
    
    dp[x][y] = 0
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0<= nx < M and 0<=ny < N:
            if maps[nx][ny] < maps[x][y]:
                dp[x][y] += dfs(nx,ny)
    return dp[x][y]
 
M,N = map(int,input().split())
maps = []
for _ in range(M):
    maps.append(list(map(int,input().split())))
    
dp = [[-1 for _ in range(N)] for _ in range(M)]
 
dx = [-1,0,0,1]
dy = [0,1,-1,0]
 
dfs(0,0)
 
print(dp[0][0])
cs

문제링크:

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

 

1520번: 내리막 길

첫째 줄에는 지도의 세로의 크기 M과 가로의 크기 N이 빈칸을 사이에 두고 주어진다. 이어 다음 M개 줄에 걸쳐 한 줄에 N개씩 위에서부터 차례로 각 지점의 높이가 빈 칸을 사이에 두고 주어진다.

www.acmicpc.net

 

'Algorithm' 카테고리의 다른 글

[BOJ]11559. Puyo Puyo  (0) 2021.09.07
[BOJ]3190. 뱀  (0) 2021.08.19
[BOJ]1987. 알파벳  (0) 2021.08.10
[BOJ]14425. 문자열 집합  (0) 2021.06.24
[Programmers]Lv 1.완주하지 못한 선수  (0) 2019.02.17

문제:

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다.

말은 상하좌우로 인접한 네 칸 중의 한 칸으로 이동할 수 있는데, 새로 이동한 칸에 적혀 있는 알파벳은 지금까지 지나온 모든 칸에 적혀 있는 알파벳과는 달라야 한다. 즉, 같은 알파벳이 적힌 칸을 두 번 지날 수 없다.

좌측 상단에서 시작해서, 말이 최대한 몇 칸을 지날 수 있는지를 구하는 프로그램을 작성하시오. 말이 지나는 칸은 좌측 상단의 칸도 포함된다.

입력:

첫째 줄에 R과 C가 빈칸을 사이에 두고 주어진다. (1 ≤ R,C ≤ 20) 둘째 줄부터 R개의 줄에 걸쳐서 보드에 적혀 있는 C개의 대문자 알파벳들이 빈칸 없이 주어진다.

출력:

첫째 줄에 말이 지날 수 있는 최대의 칸 수를 출력한다.

풀이방법:

dfs를 사용해서 이 문제를 풀 수 있다. dfs는 다음과 같이 구성되어 있다.

 

1. 한 점으로부터 시작해 상하좌우를 탐색한다. (처음은 1행 1열)

2. 상하좌우를 탐색할 때, 아직 방문하지 않았고, 처음보는 알파벳이라면 그 방향으로 다시 dfs를 탐색한다.

3. dfs를 시작하는 순간마다. 현재까지 가지고 있는 알파벳 수를 기억해서 최대 몇칸을 지날 수 있는지 확인한다.

4. 더 이상 이동하지 못하는 경우에 한 dfs를 빠져나오게 되며, 방문 기록과 알파벳 탐색 기록을 지운다.

 

최종적으로 3번을 통해 기록한 값을 출력하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import sys
input = sys.stdin.readline
 
def dfs(x,y,tmp):
    global answer
    if answer < tmp:
        answer = tmp
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0<=nx < R and 0 <=ny < C:
            if not history[ord(alphabet[nx][ny])-65and not visited[nx][ny]:
                history[ord(alphabet[nx][ny])-65= True
                visited[nx][ny] = 1
                dfs(nx,ny,tmp+1)
                visited[nx][ny] = 0
                history[ord(alphabet[nx][ny])-65= False
    
 
R,C = map(int,input().split())
alphabet = []
for _ in range(R):
    alphabet.append(list(input()))
visited = [[0 for _ in range(C)] for _ in range(R)]
dx = [-1,0,0,1]
dy = [0,-1,1,0]
 
history = [False]*26
visited[0][0= 1
history[ord(alphabet[0][0])-65= True
answer = 1
dfs(0,0,answer)
print(answer)
cs

문제링크:

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

 

1987번: 알파벳

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으

www.acmicpc.net

 

'Algorithm' 카테고리의 다른 글

[BOJ]11559. Puyo Puyo  (0) 2021.09.07
[BOJ]3190. 뱀  (0) 2021.08.19
[BOJ]1520. 내리막길  (0) 2021.08.17
[BOJ]14425. 문자열 집합  (0) 2021.06.24
[Programmers]Lv 1.완주하지 못한 선수  (0) 2019.02.17

문제:

루트 없는 트리가 주어진다. 이때, 트리의 루트를 1이라고 정했을 때, 각 노드의 부모를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 노드의 개수 N (2 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N-1개의 줄에 트리 상에서 연결된 두 정점이 주어진다.

출력:

첫째 줄부터 N-1개의 줄에 각 노드의 부모 노드 번호를 2번 노드부터 순서대로 출력한다.

풀이방법:

 nodes라는 이중배열을 사용해서 입력으로 주어지는 연결된 두 정점 사이의 관계를 기록한다. 그리고 항상 트리의 루트는 1이라고 정해졌기 때문에, 1부터 dfs를 사용해서 노드들을 탐색하면서 parent를 기록한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import sys
sys.setrecursionlimit(10**5)
= int(input())
 
nodes = [[] for _ in range(n+1)]
for _ in range(n-1):
    a, b = map(int,input().split())
    nodes[a].append(b)
    nodes[b].append(a)
    
parents = [0 for _ in range(n+1)]
parents[1= 1
    
def dfs(curr, nodes, parents):
    for n in nodes[curr]:
        if parents[n] == 0:
            parents[n] = curr
            dfs(n,nodes,parents)
        
dfs(1, nodes, parents)
for i in range(2,n+1):
    print(parents[i])
cs

문제링크:

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

 

11725번: 트리의 부모 찾기

루트 없는 트리가 주어진다. 이때, 트리의 루트를 1이라고 정했을 때, 각 노드의 부모를 구하는 프로그램을 작성하시오.

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]16234. 인구 이동  (0) 2021.07.06
[BOJ]14891. 톱니바퀴  (0) 2021.07.01
[BOJ]14725. 개미굴  (0) 2021.06.22
[BOJ]2012. 등수 매기기  (0) 2021.06.17
[BOJ]4690. 완전 세제곱  (0) 2021.06.15

문제:

두 종류의 부등호 기호 ‘<’와 ‘>’가 k개 나열된 순서열  A가 있다. 우리는 이 부등호 기호 앞뒤에 서로 다른 한 자릿수 숫자를 넣어서 모든 부등호 관계를 만족시키려고 한다. 예를 들어, 제시된 부등호 순서열 A가 다음과 같다고 하자.

A =>  < < < > < < > < >

부등호 기호 앞뒤에 넣을 수 있는 숫자는 0부터 9까지의 정수이며 선택된 숫자는 모두 달라야 한다. 아래는 부등호 순서열 A를 만족시키는 한 예이다. 

3 < 4 < 5 < 6 > 1 < 2 < 8 > 7 < 9 > 0

이 상황에서 부등호 기호를 제거한 뒤, 숫자를 모두 붙이면 하나의 수를 만들 수 있는데 이 수를 주어진 부등호 관계를 만족시키는 정수라고 한다. 그런데 주어진 부등호 관계를 만족하는 정수는 하나 이상 존재한다. 예를 들어 3456128790 뿐만 아니라 5689023174도 아래와 같이 부등호 관계 A를 만족시킨다. 

5 < 6 < 8 < 9 > 0 < 2 < 3 > 1 < 7 > 4

여러분은 제시된 k개의 부등호 순서를 만족하는 (k+1)자리의 정수 중에서 최댓값과 최솟값을 찾아야 한다. 앞서 설명한 대로 각 부등호의 앞뒤에 들어가는 숫자는 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }중에서 선택해야 하며 선택된 숫자는 모두 달라야 한다

입력:

첫 줄에 부등호 문자의 개수를 나타내는 정수 k가 주어진다. 그 다음 줄에는 k개의 부등호 기호가 하나의 공백을 두고 한 줄에 모두 제시된다. k의 범위는 2 ≤ k ≤ 9 이다. 

출력:

여러분은 제시된 부등호 관계를 만족하는 k+1 자리의 최대, 최소 정수를 첫째 줄과 둘째 줄에 각각 출력해야 한다. 단 아래 예(1)과 같이 첫 자리가 0인 경우도 정수에 포함되어야 한다. 모든 입력에 답은 항상 존재하며 출력 정수는 하나의 문자열이 되도록 해야 한다. 

풀이방법:

 처음에는 itertools의 permutation을 사용해서 풀려고 했으나, 메모리 초과가 발생했다. 아무래도 경우의 수가 엄청 많기 때문에 발생한 것 같았다.

 따라서 백트래킹(dfs)를 사용해서 효율적으로 구하려고 했다. visited 배열을 만들어서 사용한 숫자, 그렇지 않은 숫자를 구분했고, 빈 문자열로 시작했기 때문에 length==0이라는 조건을 넣어주게 되었다. is_possible 함수를 통해 부등호를 만족하는 조건의 숫자들을 구했으면 이를 answer 배열에 넣도록 한다. 

 이 때, answer 배열들의 숫자들은 작은 숫자부터 생성하기 시작했기 때문에 맨 처음에는 "부등호를 만족하는 가장 작은 숫자", 맨 마지막에는 "부등호를 만족하는 가장 큰 숫자"가 들어가 있게 된다. 따라서 이를 알맞게 출력하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def is_possible(i,op,j):
    if op == ">":
        return i > j
    else:
        return i < j
 
def dfs(length,can):
    global answer
    if length==n+1:
        answer.append(can)
        return
    for i in range(10):
        if not visited[i]:
            if length==0 or is_possible(can[-1],ie[length-1],str(i)):
                visited[i] = True
                dfs(length+1,can+str(i))
                visited[i] = False
                
n=int(input())
ie = input().split()
numbers  = list(range(10))
visited = [False]*10
answer = []
dfs(0,"")
print(answer[-1])
print(answer[0])
cs

문제링크:

www.acmicpc.net/problem/2529

 

2529번: 부등호

두 종류의 부등호 기호 ‘<’와 ‘>’가 k개 나열된 순서열  A가 있다. 우리는 이 부등호 기호 앞뒤에 서로 다른 한 자릿수 숫자를 넣어서 모든 부등호 관계를 만족시키려고 한다. 예를 들어, 제

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]1251. 단어 나누기  (0) 2021.02.02
[BOJ]1715. 카드 정렬하기  (0) 2021.01.28
[BOJ]2003. 수들의 합 2  (0) 2021.01.19
[BOJ]2661. 좋은 수열  (0) 2021.01.14
[BOJ]15711. 환상의 짝꿍  (0) 2021.01.12

문제:

은민이는 4와 7을 좋아하고, 나머지 숫자는 싫어한다. 금민수는 어떤 수가 4와 7로만 이루어진 수를 말한다.

A와 B가 주어졌을 때, A보다 크거나 같고, B보다 작거나 같은 자연수 중에 금민수인 것의 개수를 출력하는 프로그램을 작성하시오.

입력:

첫째 줄에 A와 B가 주어진다. A는 1보다 크거나 같고, 1,000,000,000보다 작거나 같은 자연수이다. B는 A보다 크거나 같고, 1,000,000,000보다 작거나 같은 자연수이다.

출력:

첫째 줄에 A보다 크거나 같고, B보다 작거나 같은 자연수 중에 금민수인 것의 개수를 출력한다.

풀이방법:

 주어진 수가 1,000,000,000로 엄청 크게 주어졌기 때문에 A~B 사이의 수가 4와 7로 이루어져있는지 탐색하는 것은 시간초과가 발생할 것이다. 따라서4와 7로 구성된 숫자를 만들면서 이 숫자가 A~B 사이에 있는지 확인하도록 한다.

 A와 B가 큰 수로 주어질 수도 있기 때문에 깊이라는 개념을 사용해서 최대한 탐색할 수 있도록 했다. 깊이는 상한값으로 인해 최대 9까지 가능하다. 깊이라는 개념이 추가되었기 때문에 깊이우선탐색을 사용해서 값을 만들어내도록 한다.

 생성된 값이 주어진 범위 안에 들어 있으면 count를 1 올려주고 상한 값을 넘어가면 더 빠른 탐색을 위해서 0을 반환하도록 했다. 하한값에 보다 작은 값에 대해서는 조건이 없는데, 그 이유는 앞서 말했던 A와 B가 큰 수로 주어졌을 때, 그 범위 내까지는 이동하도록 하기 위함이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def dfs(lower,upper,depth,number):
    answer = 0
    if (depth>=10):
        return 0
    if number > upper:
        return 0
    if upper>= number >= lower:
        answer+=1
    answer +=dfs(lower,upper,depth+1,number*10+4)
    answer +=dfs(lower,upper,depth+1,number*10+7)
    return answer
 
A,B = map(int,input().split())
 
ans = dfs(A,B,0,0)
print(ans)
cs

문제링크:

www.acmicpc.net/problem/1527

 

1527번: 금민수의 개수

첫째 줄에 A와 B가 주어진다. A는 1보다 크거나 같고, 1,000,000,000보다 작거나 같은 자연수이다. B는 A보다 크거나 같고, 1,000,000,000보다 작거나 같은 자연수이다.

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]13908. 비밀번호  (0) 2020.12.29
[BOJ]11723. 집합  (0) 2020.12.24
[BOJ]7453. 합이 0인 네 정수  (0) 2020.12.10
[BOJ]2294. 동전 2  (0) 2020.12.08
[BOJ]11060. 점프 점프  (0) 2020.12.03

문제:

그래프의 정점의 집합을 둘로 분할하여, 각 집합에 속한 정점끼리는 서로 인접하지 않도록 분할할 수 있을 때, 그러한 그래프를 특별히 이분 그래프 (Bipartite Graph) 라 부른다.

그래프가 입력으로 주어졌을 때, 이 그래프가 이분 그래프인지 아닌지 판별하는 프로그램을 작성하시오.

입력:

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수 E(1≤E≤200,000)가 빈 칸을 사이에 두고 순서대로 주어진다. 각 정점에는 1부터 V까지 차례로 번호가 붙어 있다. 이어서 둘째 줄부터 E개의 줄에 걸쳐 간선에 대한 정보가 주어지는데, 각 줄에 인접한 두 정점의 번호가 빈 칸을 사이에 두고 주어진다.

출력:

K개의 줄에 걸쳐 입력으로 주어진 그래프가 이분 그래프이면 YES, 아니면 NO를 순서대로 출력한다.

풀이방법:

 위키피디아에 따르면 이분 그래프란 모든 꼭짓점을 빨강과 파랑으로 색칠하되, 모든 변이 빨강과 파랑 꼭짓점을 포함하도록 색칠할 수 있는 그래프이다. 즉 한 변의 양 끝은 빨강과 파랑으로 서로 달라야 한다는 것이다.

 dfs로 정점을 탐색하며, visited에다 색을 기록한다. dfs로 탐색하는 도중에 visited에 서로 다른 색이 들어오게 되면 이분그래프가 아니므로 False를 반환하도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import sys
 
sys.setrecursionlimit(10**6)
input = sys.stdin.readline
 
def dfs(cur,color):
    visited[cur] = color
    for i in vertex[cur]:
        if visited[i]==0:
            if not dfs(i,-color):
                return False
        elif visited[i] == visited[cur]:
            return False
    return True
 
= int(input())
for _ in range(K):
    V, E = map(int,input().split())
    vertex = [[] for _ in range(V+1)]
    visited = [0 for _ in range(V+1)]
    for _ in range(E):
        x, y = map(int,input().split())
        vertex[x].append(y)
        vertex[y].append(x)
        
    answer = True
    for i in range(1,V+1):
        if visited[i] == 0:
            if not dfs(i,1):
                answer=False
                break
    if answer:
        print("YES")
    else:
        print("NO")
cs

문제링크:

www.acmicpc.net/problem/1707

 

1707번: 이분 그래프

입력은 여러 개의 테스트 케이스로 구성되어 있는데, 첫째 줄에 테스트 케이스의 개수 K(2≤K≤5)가 주어진다. 각 테스트 케이스의 첫째 줄에는 그래프의 정점의 개수 V(1≤V≤20,000)와 간선의 개수

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]10835. 카드게임  (0) 2020.12.01
[BOJ]1747. 소수&팰린드롬  (0) 2020.11.26
[BOJ]7562. 나이트의 이동  (0) 2020.11.19
[BOJ]1992. 쿼드트리  (0) 2020.11.17
[BOJ]1041. 주사위  (0) 2020.11.12

문제:

2048 게임은 4x4 크기의 보드에서 혼자 즐기는 게임이다. 

 

이 게임에서 한 번의 이동은 보드 위에 있는 전체 블록을 상하좌우 네 방향 중 하나로 이동시키는 것이다. 이때, 같은 값을 갖는 두 블록이 충돌하면 두 블록은 하나로 합쳐지게 된다. 한 번의 이동에서 이미 합쳐진 블록은 또 다른 블록과 디시 합쳐질 수 없다. (실제 게임에서는 이동을 한 번 할 때마다 블록이 추가되지만, 이 문제에서 블록이 추가되는 경우는 없다)

 

이 문제에서 다루는 2048 게임은 보드의 크기가 NxN이다. 보드의 크기와 보드판의 블록 상태가 주어졌을 때, 쵣 5번 이동해서 만들 수 있는 가장 큰 불록의 값을 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 보드의 크기 N (1<=N<=20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.

출력:

최대 5번 이동시켜서 얻을 수 있는 가장 큰 블록을 출력한다.

풀이방법:

최대 5번만 이동하면 되기 때문에 dfs를 사용해서 모든 경우를 탐색하고, 그 중 가장 최댓값을 찾아내도록 하면 된다.

반복문을 사용해서 상하좌우로 이동하게 만들었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import copy
 
def dfs(numbers,count):
    global answer
    if count==5:
        if max(max(numbers,key=lambda x : max(x))) > answer:
            answer = max(max(numbers,key=lambda x : max(x)))
        return
    count+=1
    for i in range(4):
        if i==0:
            numberT = copy.deepcopy(numbers)
            for j in range(N):
                tmp = -1
                temp = []
                for num in numberT[j]:
                    if num == 0:
                        continue
                    if len(temp)==0:
                        temp.append(num)
                        tmp = num
                    else:
                        if tmp==num and temp[-1]==num:
                            temp[-1]=num*2
                        else:
                            temp.append(num)
                        tmp = num
                if len(temp)!=N:
                    while len(temp)<N:
                        temp.append(0)
                numberT[j]=temp
            dfs(numberT,count)
        if i==1:
            numberT = copy.deepcopy(numbers)
            for j in range(N):
                tmp = -1
                temp = []
                for k in range(N-1,-1,-1):
                    if numberT[k][j]==0:
                        continue
                    if len(temp)==0:
                        temp.append(numberT[k][j])
                        tmp = numberT[k][j]
                    else:
                        if tmp == numberT[k][j] and temp[-1]==numberT[k][j]:
                            temp[-1]=numberT[k][j]*2
                        else:
                            temp.append(numberT[k][j])
                        tmp = numberT[k][j]
                temp.reverse()
                if len(temp)!=N:
                    while len(temp)<N:
                        temp.insert(0,0)
                for k in range(N):
                    numberT[k][j]=temp[k]
            dfs(numberT,count)
        elif i==2:
            numberT = copy.deepcopy(numbers)
            for j in range(N):
                tmp = -1
                temp = []
                for num in list(reversed(numberT[j])):
                    if num == 0:
                        continue
                    if len(temp)==0:
                        temp.append(num)
                        tmp = num
                    else:
                        if tmp == num and temp[-1]==num:
                            temp[-1]=num*2
                        else:
                            temp.append(num)
                        tmp = num
                if len(temp)!=N:
                    while len(temp)<N:
                        temp.append(0)
                numberT[j]=list(reversed(temp))
            dfs(numberT,count)
        elif i==3:
            numberT = copy.deepcopy(numbers)
            for j in range(N):
                tmp = -1
                temp = []
                for k in range(N):
                    if numberT[k][j] == 0:
                        continue
                    if len(temp)==0:
                        temp.append(numberT[k][j])
                        tmp = numberT[k][j]
                    else:
                        if tmp == numberT[k][j] and temp[-1]==numberT[k][j]:
                            temp[-1]=numberT[k][j]*2
                        else:
                            temp.append(numberT[k][j])
                        tmp = numberT[k][j]
                if len(temp)!=N:
                    while len(temp)<N:
                        temp.append(0)
                for k in range(N):
                    numberT[k][j]=temp[k]
            dfs(numberT,count)
 
= int(input())
numbers = []
for _ in range(N):
    numbers.append(list(map(int,input().split())))
 
answer = -1
count = 0
dfs(numbers,count)
print(answer)
cs

문제링크:

www.acmicpc.net/problem/12100

 

12100번: 2048 (Easy)

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2

www.acmicpc.net

 

'Algorithm > Python' 카테고리의 다른 글

[BOJ]19948. 음유시인 영재  (0) 2020.10.15
[BOJ]1644. 소수의 연속합  (0) 2020.10.13
[BOJ]1806 부분합  (0) 2020.09.22
[BOJ]2096. 내려가기  (0) 2020.09.15
[BOJ]10972. 다음 순열  (0) 2020.09.10

+ Recent posts