728x90

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

 

15685번: 드래곤 커브

첫째 줄에 드래곤 커브의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 드래곤 커브의 정보가 주어진다. 드래곤 커브의 정보는 네 정수 x, y, d, g로 이루어져 있다. x와 y는 드래곤 커

www.acmicpc.net

출처 : 백준


문제

드래곤 커브는 다음과 같은 세 가지 속성으로 이루어져 있으며, 이차원 좌표 평면 위에서 정의된다. 좌표 평면의 x축은 → 방향, y축은 ↓ 방향이다.

  1. 시작 점
  2. 시작 방향
  3. 세대

0세대 드래곤 커브는 아래 그림과 같은 길이가 1인 선분이다. 아래 그림은 (0, 0)에서 시작하고, 시작 방향은 오른쪽인 0세대 드래곤 커브이다.

1세대 드래곤 커브는 0세대 드래곤 커브를 끝 점을 기준으로 시계 방향으로 90도 회전시킨 다음 0세대 드래곤 커브의 끝 점에 붙인 것이다. 끝 점이란 시작 점에서 선분을 타고 이동했을 때, 가장 먼 거리에 있는 점을 의미한다.

2세대 드래곤 커브도 1세대를 만든 방법을 이용해서 만들 수 있다. (파란색 선분은 새로 추가된 선분을 나타낸다)

3세대 드래곤 커브도 2세대 드래곤 커브를 이용해 만들 수 있다. 아래 그림은 3세대 드래곤 커브이다.

즉, K(K > 1)세대 드래곤 커브는 K-1세대 드래곤 커브를 끝 점을 기준으로 90도 시계 방향 회전 시킨 다음, 그것을 끝 점에 붙인 것이다.

크기가 100×100인 격자 위에 드래곤 커브가 N개 있다. 이때, 크기가 1×1인 정사각형의 네 꼭짓점이 모두 드래곤 커브의 일부인 정사각형의 개수를 구하는 프로그램을 작성하시오. 격자의 좌표는 (x, y)로 나타내며, 0 ≤ x ≤ 100, 0 ≤ y ≤ 100만 유효한 좌표이다.

입력

첫째 줄에 드래곤 커브의 개수 N(1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 드래곤 커브의 정보가 주어진다. 드래곤 커브의 정보는 네 정수 x, y, d, g로 이루어져 있다. x와 y는 드래곤 커브의 시작 점, d는 시작 방향, g는 세대이다. (0 ≤ x, y ≤ 100, 0 ≤ d ≤ 3, 0 ≤ g ≤ 10)

입력으로 주어지는 드래곤 커브는 격자 밖으로 벗어나지 않는다. 드래곤 커브는 서로 겹칠 수 있다.

방향은 0, 1, 2, 3 중 하나이고, 다음을 의미한다.

  • 0: x좌표가 증가하는 방향 (→)
  • 1: y좌표가 감소하는 방향 (↑)
  • 2: x좌표가 감소하는 방향 (←)
  • 3: y좌표가 증가하는 방향 (↓)

출력

첫째 줄에 크기가 1×1인 정사각형의 네 꼭짓점이 모두 드래곤 커브의 일부인 것의 개수를 출력한다.

코드

import sys
n = int(sys.stdin.readline())
dx = [1, 0, -1, 0]
dy = [0, -1, 0, 1]
graph = [[0]*101 for _ in range(101)]

for i in range(n):
    x, y, d, g = map(int,sys.stdin.readline().split())
    graph[x][y] = 1

# 커브 변화 배열 만들기
    curv = [d]
    for ge in range(g):
        for c in range(len(curv)-1, -1, -1):
            curv.append((curv[c]+1) % 4)
            
# 드래곤 커브 돌면서 방문 표시
    for i in range(len(curv)):
        x += dx[curv[i]]
        y += dy[curv[i]]
        if 0 <= x <= 100 and 0 <= y <= 100:
            graph[x][y] = 1

# 1x1인 정사각형의 네 꼭짓점이 모두 드래곤 커브인 경우 개수
answer = 0
for i in range(100):
    for j in range(100):
        if graph[i][j] == 1 and graph[i+1][j] == 1 and graph[i][j+1]==1 and graph[i+1][j+1]==1:
            answer += 1
print(answer)

풀이

시작 방향 d를 보면

0 (1, 0)

1 (0, -1)

2 (-1, 0)

3 (0, 1)

다음과 같다.

 

세대 별로 방향의 변동의 규칙을 찾아보면 위의 그림과 같다.

인접한 방향 배열에서 1을 더하는 것이다.

728x90

문제

두 자연수 A와 B가 있을 때, A = BC를 만족하는 자연수 C를 A의 약수라고 한다. 예를 들어, 2의 약수는 1, 2가 있고, 24의 약수는 1, 2, 3, 4, 6, 8, 12, 24가 있다. 자연수 A의 약수의 합은 A의 모든 약수를 더한 값이고, f(A)로 표현한다. x보다 작거나 같은 모든 자연수 y의 f(y)값을 더한 값은 g(x)로 표현한다.

자연수 N이 주어졌을 때, g(N)을 구해보자.

입력

첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

출력

첫째 줄에 g(N)를 출력한다.

코드

import sys

n = int(sys.stdin.readline())
answer = 0
for i in range(1,n+1):
    answer += (n//i) *i
print(answer)

풀이

바로 생각해내기 어려웠다.

 

2의 배수를 생각해보자.

2, 4, 6, 8, ... 당연히 2의 배수니까 모든 배수에 2가 포함되어 있다. 

n이 4라면 4//2 = 2  -> 2가 2번 있다.

n이 8라면 8//2 = 4 -> 2가 4번 있다.

.... 

i 가 n // i 번 있다는 것이다.

그래서  아래와 같이 코드를 작성했다.

answer += (n//i) *i

 

 

출처 : 백준

728x90

문제

그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때문에 그룹 단어이지만, aabbbccb는 b가 떨어져서 나타나기 때문에 그룹 단어가 아니다.

단어 N개를 입력으로 받아 그룹 단어의 개수를 출력하는 프로그램을 작성하시오.

입력

첫째 줄에 단어의 개수 N이 들어온다. N은 100보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 단어가 들어온다. 단어는 알파벳 소문자로만 되어있고 중복되지 않으며, 길이는 최대 100이다.

출력

첫째 줄에 그룹 단어의 개수를 출력한다.

코드

import sys
n = int(sys.stdin.readline())
cnt = 0
for i in range(n):
    s = sys.stdin.readline().rstrip()
    new_word = [s[0]]
    err = 0
    for a in range(len(s)-1):
        if s[a] != s[a+1]:
            if s[a+1] in new_word:
                err += 1
            new_word.append(s[a+1])

    if err == 0:
        cnt += 1
print(cnt)

풀이

입력받은 문자열을 한 글자씩 비교하면서 다른 글자가 나오면 new_word에 넣는다.

이때, new_word에 있는 글자라면 그룹 단어가 되지 않으니 체크한다.

 

출처 : 백준

728x90

문제

1부터 N까지의 수로 이루어진 순열이 있다. 이때, 사전순으로 다음에 오는 순열을 구하는 프로그램을 작성하시오.

사전 순으로 가장 앞서는 순열은 오름차순으로 이루어진 순열이고, 가장 마지막에 오는 순열은 내림차순으로 이루어진 순열이다.

N = 3인 경우에 사전순으로 순열을 나열하면 다음과 같다.

  • 1, 2, 3
  • 1, 3, 2
  • 2, 1, 3
  • 2, 3, 1
  • 3, 1, 2
  • 3, 2, 1

입력

첫째 줄에 N(1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄에 순열이 주어진다.

출력

첫째 줄에 입력으로 주어진 순열의 다음에 오는 순열을 출력한다. 만약, 사전순으로 마지막에 오는 순열인 경우에는 -1을 출력한다.

코드

# 10972
import sys
n = int(sys.stdin.readline())
arr = list(map(int,sys.stdin.readline().split()))
x = 0
for i in range(n-1, 0, -1):
    if arr[i] > arr[i-1]:
        x = i-1
        break
for i in range(n-1, 0, -1):
    if arr[x] < arr[i]:
        arr[x], arr[i] = arr[i], arr[x]
        arr = arr[:x+1] + sorted(arr[x+1:])
        print(*arr)
        exit()
print(-1)

풀이

 next_permutation

  1. 순열의 뒤 부터 비교하며 뒷 값이 앞 값 보다 큰 인덱스 구해서 x에 앞 값 인덱스 넣기
  2. 이 x 값과 다시 순열의 뒤부터 비교해서 arr[x] 보다 큰 값 구하고 swap 진행하기
  3. x 다음 값이 큰 값이었다.
  4. 이 값 기준으로 앞은 그대로, 뒤는 sorted 해서 포인트로 접근 print()
  5. exit() 종료
728x90

문제

준규가 사는 나라는 우리가 사용하는 연도와 다른 방식을 이용한다. 준규가 사는 나라에서는 수 3개를 이용해서 연도를 나타낸다. 각각의 수는 지구, 태양, 그리고 달을 나타낸다.

지구를 나타내는 수를 E, 태양을 나타내는 수를 S, 달을 나타내는 수를 M이라고 했을 때, 이 세 수는 서로 다른 범위를 가진다. (1 ≤ E ≤ 15, 1 ≤ S ≤ 28, 1 ≤ M ≤ 19)

우리가 알고있는 1년은 준규가 살고있는 나라에서는 1 1 1로 나타낼 수 있다. 1년이 지날 때마다, 세 수는 모두 1씩 증가한다. 만약, 어떤 수가 범위를 넘어가는 경우에는 1이 된다.

예를 들어, 15년은 15 15 15로 나타낼 수 있다. 하지만, 1년이 지나서 16년이 되면 16 16 16이 아니라 1 16 16이 된다. 이유는 1 ≤ E ≤ 15 라서 범위를 넘어가기 때문이다.

E, S, M이 주어졌고, 1년이 준규가 사는 나라에서 1 1 1일때, 준규가 사는 나라에서 E S M이 우리가 알고 있는 연도로 몇 년인지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 세 수 E, S, M이 주어진다. 문제에 나와있는 범위를 지키는 입력만 주어진다.

출력

첫째 줄에 E S M으로 표시되는 가장 빠른 연도를 출력한다. 1 1 1은 항상 1이기 때문에, 정답이 음수가 나오는 경우는 없다.

코드

# 1476

import sys
e, s, m = map(int,sys.stdin.readline().split())
cnt = 1
starte, starts, startm = 1,1,1
while True:
    if starte == e and starts == s and startm == m:
        break
    starte += 1
    starts += 1
    startm += 1
    cnt += 1
    if starte > 15:
        starte = 1
    if starts > 28:
        starts = 1
    if startm > 19:
        startm = 1

print(cnt)

풀이

1 1 1 을 1년 지날 때마다 모두 +1 해주며 e, s, m 값과 같아질 때까지 cnt+=1 해준다.

+1 해줄 때, e,s,m 의 범위 넘으면 다시 1로 초기화해준다.

728x90

문제

상근이는 어렸을 적에 "봄보니 (Bomboni)" 게임을 즐겨했다.

가장 처음에 N×N크기에 사탕을 채워 놓는다. 사탕의 색은 모두 같지 않을 수도 있다. 상근이는 사탕의 색이 다른 인접한 두 칸을 고른다. 그 다음 고른 칸에 들어있는 사탕을 서로 교환한다. 이제, 모두 같은 색으로 이루어져 있는 가장 긴 연속 부분(행 또는 열)을 고른 다음 그 사탕을 모두 먹는다.

사탕이 채워진 상태가 주어졌을 때, 상근이가 먹을 수 있는 사탕의 최대 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 보드의 크기 N이 주어진다. (3 ≤ N ≤ 50)

다음 N개 줄에는 보드에 채워져 있는 사탕의 색상이 주어진다. 빨간색은 C, 파란색은 P, 초록색은 Z, 노란색은 Y로 주어진다.

사탕의 색이 다른 인접한 두 칸이 존재하는 입력만 주어진다.

출력

첫째 줄에 상근이가 먹을 수 있는 사탕의 최대 개수를 출력한다.

코드

# 3085

import sys
n = int(sys.stdin.readline())
arr = [list(sys.stdin.readline().strip()) for _ in range(n)]
answer = 0

# 완전 탐색
def check(array):
    max_len = 1 # 함수의 리턴 값 -> 가장 긴 최대 길이
    for i in range(n):
        # 열 비교
        cnt = 1 # 같은 색인 최대 길이
        for j in range(1,n):
            if arr[i][j] == arr[i][j-1]:
                cnt += 1
            else: # 인접한 사탕 중 다른 색 나오면 cnt 초기화
                cnt = 1
            max_len = max(max_len, cnt) # max_len 갱신
        
        # 행 비교
        cnt = 1  # 같은 색인 최대 길이
        for j in range(1,n):
            if arr[j][i] == arr[j-1][i]:
                cnt += 1
            else:
                cnt = 1
            max_len = max(max_len, cnt)  # max_len 갱신
    return max_len

# 인접하고 색 다른 두 칸 고르고 완탐 호출
for i in range(n):
    for j in range(n):
        if j+1<n: # 인접한 열 끼리 비교 후 교체
            if arr[i][j] != arr[i][j+1]:
                arr[i][j],arr[i][j+1] = arr[i][j+1], arr[i][j]
                # 완전탐색 수행
                tmp = check(arr)
                # 정답과 완탐 CNT 비교
                answer = max(answer,tmp)
                # 교체 한 것 다시 원래대로 돌려놓기 ( 모든 경우의수 비교해야함)
                arr[i][j], arr[i][j + 1] = arr[i][j + 1], arr[i][j]

        if i+1<n: # 인접한 행 끼리 비교 후 교체
            if arr[i][j] != arr[i+1][j]:
                arr[i][j], arr[i + 1][j] = arr[i + 1][j],arr[i][j]
                # 완전탐색 수행
                tmp = check(arr)
                # 정답과 완탐 CNT 비교
                answer = max(answer, tmp)
                # 교체 한 것 다시 원래대로 돌려놓기 ( 모든 경우의수 비교해야함)
                arr[i][j], arr[i + 1][j] = arr[i + 1][j], arr[i][j]
print(answer)

풀이

보드의 크기 N이 주어진다. (3 ≤ N ≤ 50) -> 완전 탐색 가능하다.

 

1. 색이 다른 인접한 두 사탕 선택 후 교체

2. 교체한 배열에서 같은 사탕 색이 있는 (행 또는 열) 최대 길이 구하기

3. 교체한 사탕 다시 제자리로 위치시키고 다음 인접한 사탕 교체 후 완전탐색 반복

 

계속 교체할 사탕 2개 선택해서 자리 바꾸고 완탐으로 최대 길이 구하고 리턴 시켜서

answer 값을 max 값으로 갱신시킨다.

 

이 문제 괜찮은 것 같다.

나중에 다시 풀어보자.

 

728x90

문제

방향 없는 그래프가 주어졌을 때, 연결 요소 (Connected Component)의 개수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 정점의 개수 N과 간선의 개수 M이 주어진다. (1 ≤ N ≤ 1,000, 0 ≤ M ≤ N×(N-1)/2) 둘째 줄부터 M개의 줄에 간선의 양 끝점 u와 v가 주어진다. (1 ≤ u, v ≤ N, u ≠ v) 같은 간선은 한 번만 주어진다.

출력

첫째 줄에 연결 요소의 개수를 출력한다.

풀이 1 (DFS)

# 11724
import sys
sys.setrecursionlimit(10000)
n,m = map(int,sys.stdin.readline().split())
graph = [[] for _ in range(n+1)]
visited = [0]*(n+1)
cnt = 0
for _ in range(m):
    u,v = map(int,sys.stdin.readline().split())
    graph[u].append(v)
    graph[v].append(u)
# print(graph)

def dfs(node):
    visited[node] = 1
    for i in graph[node]:
        if not visited[i]:
            dfs(i)

for i in range(1,n+1):
    if not visited[i]:
        dfs(i)
        cnt += 1
print(cnt)

풀이 2 (BFS)

# 11724
import sys
# sys.setrecursionlimit(10000)
from collections import deque
n,m = map(int,sys.stdin.readline().split())
graph = [[] for _ in range(n+1)]
visited = [0]*(n+1)
cnt = 0
for _ in range(m):
    u,v = map(int,sys.stdin.readline().split())
    graph[u].append(v)
    graph[v].append(u)
# print(graph)

def bfs(graph, node, visited):
    visited[node] = 1
    q = deque([node])
    while q:
        v = q.popleft()
        for i in graph[v]:
            if not visited[i]:
                q.append(i)
                visited[i] = 1

for i in range(1,n+1):
    if not visited[i]:
        bfs(graph, i, visited)
        cnt += 1
print(cnt)

 

+ Recent posts