728x90
반응형

문제:

KOI 어린이집에는 N명의 아이들이 있다. 오늘은 소풍을 가는 날이다. 선생님은 1번부터 N번까지 번호가 적혀있는 번호표를 아이들의 가슴에 붙여주었다. 선생님은 아이들을 효과적으로 보호하기 위해 목적지까지 번호순서대로 일렬로 서서 걸어가도록 하였다. 이동 도중에 보니 아이들의 번호순서가 바뀌었다. 그래서 선생님은 다시 번호 순서대로 줄을 세우기 위해서 아이들의 위치를 옮기려고 한다. 그리고 아이들이 혼란스러워하지 않도록 하기 위해 위치를 옮기는 아이들의 수를 최소로 하려고 한다.

예를 들어, 7명의 아이들이 다음과 같은 순서대로 줄을 서 있다고 하자.

3 7 5 2 6 1 4

아이들을 순서대로 줄을 세우기 위해, 먼저 4번 아이를 7번 아이의 뒤로 옮겨보자. 그러면 다음과 같은 순서가 된다.

3 7 4 5 2 6 1

이제, 7번 아이를 맨 뒤로 옮긴다.

3 4 5 2 6 1 7

다음 1번 아이를 맨 앞으로 옮긴다.

1 3 4 5 2 6 7

마지막으로 2번 아이를 1번 아이의 뒤로 옮기면 번호 순서대로 배치된다.

1 2 3 4 5 6 7

위의 방법으로 모두 4명의 아이를 옮겨 번호 순서대로 줄을 세운다. 위의 예에서 3명의 아이만을 옮겨서는 순서대로 배치할 수가 없다. 따라서, 4명을 옮기는 것이 가장 적은 수의 아이를 옮기는 것이다.

N명의 아이들이 임의의 순서로 줄을 서 있을 때, 번호 순서대로 배치하기 위해 옮겨지는 아이의 최소 수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에는 아이들의 수 N이 주어진다. 둘째 줄부터는 1부터 N까지의 숫자가 한 줄에 하나씩 주어진다. N은 2 이상 200 이하의 정수이다.

출력:

첫째 줄에는 번호 순서대로 줄을 세우는데 옮겨지는 아이들의 최소 수를 출력한다.

풀이방법:

 N명의 아이들을 번호 순서대로 배치하기 위해 최소의 움직임을 구한다는 것은 LIS 문제와 같다. 가장 긴 부분 수열을 찾고, 그 수열에 속하지 않은 아이들만 움직이는 것이 최소 움직임일 것이기 때문이다.

 따라서 DP를 사용한 LIS 문제를 풀고, N에서 그 값을 빼주도록 한다.

1
2
3
4
5
6
7
8
9
10
11
12
= int(input())
list_ = []
for _ in range(N):
    list_.append(int(input()))
    
dp = [1]*N
for i in range(N):
    for j in range(i):
        if list_[i] > list_[j]:
            dp[i] = max(dp[i],dp[j]+1)
            
print(N-max(dp))
cs

문제링크:

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

 

2631번: 줄세우기

KOI 어린이집에는 N명의 아이들이 있다. 오늘은 소풍을 가는 날이다. 선생님은 1번부터 N번까지 번호가 적혀있는 번호표를 아이들의 가슴에 붙여주었다. 선생님은 아이들을 효과적으로 보호하기

www.acmicpc.net

 

728x90
반응형

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

[BOJ]2660. 회장뽑기  (0) 2022.02.10
[BOJ]10827. a^b  (0) 2022.02.09
[BOJ] 9576. 책 나눠주기  (0) 2022.02.07
[BOJ]21610. 마법사 상어와 비바라기  (0) 2021.11.05
[BOJ]20057. 마법사 상어와 토네이도  (0) 2021.11.04
728x90
반응형

문제:

백준이는 방 청소를 하면서 필요 없는 전공 서적을 사람들에게 나눠주려고 한다. 나눠줄 책을 모아보니 총 N권이었다. 책이 너무 많기 때문에 백준이는 책을 구분하기 위해 각각 1부터 N까지의 정수 번호를 중복되지 않게 매겨 두었다.

조사를 해 보니 책을 원하는 서강대학교 학부생이 총 M명이었다. 백준이는 이 M명에게 신청서에 두 정수 a, b (1 ≤ a ≤ b ≤ N)를 적어 내라고 했다. 그러면 백준이는 책 번호가 a 이상 b 이하인 책 중 남아있는 책 한 권을 골라 그 학생에게 준다. 만약 a번부터 b번까지의 모든 책을 이미 다른 학생에게 주고 없다면 그 학생에게는 책을 주지 않는다.

백준이가 책을 줄 수 있는 최대 학생 수를 구하시오.

입력:

첫째 줄에 테스트 케이스의 수가 주어진다.

각 케이스의 첫 줄에 정수 N(1 ≤ N ≤ 1,000)과 M(1 ≤ M ≤ 1,000)이 주어진다. 다음 줄부터 M개의 줄에는 각각 정수 ai, bi가 주어진다. (1 ≤ ai ≤ bi ≤ N)

출력:

각 테스트 케이스마다 백준이가 책을 줄 수 있는 최대 학생 수를 한 줄에 하나씩 출력한다.

풀이방법:

 greedy하게 문제를 풀어주도록 한다. 다만, greedy한 조건 내에 범위가 짧은(a와 b의 차가 작은) 것 부터 먼저 배치하도록 한다. (1,3), (1,2), (1,2) 의 경우 모두에게 책을 줄 수 있지만 추가 조건이 없다면 답이 2로 나올 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from collections import deque
 
test_case = int(input())
 
for tc in range(test_case):
    N, M = map(int, input().split())
    visited=[0]*(N+1)
    list_ = []
    for _ in range(M):
        a,b = map(int,input().split())
        list_.append((a,b))
    list_ = sorted(list_, key=lambda x: x[1])
    answer = 0
    for a, b in list_:
        for i in range(a,b+1):
            if not visited[i]:
                answer+=1
                visited[i] = 1
                break
    print(answer)
cs

문제링크:

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

 

9576번: 책 나눠주기

백준이는 방 청소를 하면서 필요 없는 전공 서적을 사람들에게 나눠주려고 한다. 나눠줄 책을 모아보니 총 N권이었다. 책이 너무 많기 때문에 백준이는 책을 구분하기 위해 각각 1부터 N까지의

www.acmicpc.net

 

728x90
반응형

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

[BOJ]10827. a^b  (0) 2022.02.09
[BOJ]2631. 줄세우기  (0) 2022.02.08
[BOJ]21610. 마법사 상어와 비바라기  (0) 2021.11.05
[BOJ]20057. 마법사 상어와 토네이도  (0) 2021.11.04
[BOJ] 15685. 드래곤 커브  (0) 2021.11.03
728x90
반응형

문제:

마법사 상어는 파이어볼토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기를 크기가 N×N인 격자에서 연습하려고 한다. 격자의 각 칸에는 바구니가 하나 있고, 바구니는 칸 전체를 차지한다. 바구니에 저장할 수 있는 물의 양에는 제한이 없다. (r, c)는 격자의 r행 c열에 있는 바구니를 의미하고, A[r][c]는 (r, c)에 있는 바구니에 저장되어 있는 물의 양을 의미한다.

격자의 가장 왼쪽 윗 칸은 (1, 1)이고, 가장 오른쪽 아랫 칸은 (N, N)이다. 마법사 상어는 연습을 위해 1번 행과 N번 행을 연결했고, 1번 열과 N번 열도 연결했다. 즉, N번 행의 아래에는 1번 행이, 1번 행의 위에는 N번 행이 있고, 1번 열의 왼쪽에는 N번 열이, N번 열의 오른쪽에는 1번 열이 있다.

비바라기를 시전하면 (N, 1), (N, 2), (N-1, 1), (N-1, 2)에 비구름이 생긴다. 구름은 칸 전체를 차지한다. 이제 구름에 이동을 M번 명령하려고 한다. i번째 이동 명령은 방향 di과 거리 si로 이루어져 있다. 방향은 총 8개의 방향이 있으며, 8개의 정수로 표현한다. 1부터 순서대로 ←, ↖, ↑, ↗, →, ↘, ↓, ↙ 이다. 이동을 명령하면 다음이 순서대로 진행된다.

  1. 모든 구름이 di 방향으로 si칸 이동한다.
  2. 각 구름에서 비가 내려 구름이 있는 칸의 바구니에 저장된 물의 양이 1 증가한다.
  3. 구름이 모두 사라진다.
  4. 2에서 물이 증가한 칸 (r, c)에 물복사버그 마법을 시전한다. 물복사버그 마법을 사용하면, 대각선 방향으로 거리가 1인 칸에 물이 있는 바구니의 수만큼 (r, c)에 있는 바구니의 물이 양이 증가한다.
    • 이때는 이동과 다르게 경계를 넘어가는 칸은 대각선 방향으로 거리가 1인 칸이 아니다.
    • 예를 들어, (N, 2)에서 인접한 대각선 칸은 (N-1, 1), (N-1, 3)이고, (N, N)에서 인접한 대각선 칸은 (N-1, N-1)뿐이다.
  5. 바구니에 저장된 물의 양이 2 이상인 모든 칸에 구름이 생기고, 물의 양이 2 줄어든다. 이때 구름이 생기는 칸은 3에서 구름이 사라진 칸이 아니어야 한다.

M번의 이동이 모두 끝난 후 바구니에 들어있는 물의 양의 합을 구해보자.

입력:

첫째 줄에 N, M이 주어진다.

둘째 줄부터 N개의 줄에는 N개의 정수가 주어진다. r번째 행의 c번째 정수는 A[r][c]를 의미한다.

다음 M개의 줄에는 이동의 정보 di, si가 순서대로 한 줄에 하나씩 주어진다.

출력:

첫째 줄에 M번의 이동이 모두 끝난 후 바구니에 들어있는 물의 양의 합을 출력한다.

풀이방법:

 문제에서 주어진 명령어을 순서대로 진행하면 된다. 각 명령에서 다음과 같은 사항들을 주의하면 된다.

 

1. 구름이 이동할 때, 행1-행N, 열1-열N 은 연결되어 있기 때문에 % 명령어를 사용해서 구름을 이동시킨다.

2, 3. 이동한 구름의 위치를 새 배열에 담아서 +1과 이전 구름이 사라진다는 것을 구현한다.

4. 이동할 수 있는 대각선 위치에 물이 1이라도 있는지 확인하고 매번 +1한다.

5. 전체적으로 탐색을 하면서 물이 2 이상인지 확인한다.( 2,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
34
35
36
37
38
39
40
41
42
43
44
45
dx = [0,-1,-1,-1,0,1,1,1]
dy = [-1,-1,0,1,1,1,0,-1]
 
N, M = map(int, input().split())
 
maps = []
for _ in range(N):
    maps.append(list(map(int, input().split())))
 
command = []
for _ in range(M):
    command.append(list(map(int, input().split())))
 
goorm = [(N-1,0),(N-1,1),(N-2,0),(N-2,1)]
 
for com in command:
    d, s = com
    move_goorm = []
    for x, y in goorm:
        nx = (x + dx[d-1]*s)%N
        ny = (y + dy[d-1]*s)%N
        move_goorm.append((nx,ny))
    for x, y in move_goorm:
        maps[x][y] += 1
    for x, y in move_goorm:
        for i in [1,3,5,7]:
            nx = x + dx[i]
            ny = y + dy[i]
            if 0<=nx<and 0<=ny<N:
                if maps[nx][ny]:
                    maps[x][y]+=1
    goorm = []
    for i in range(N):
        for j in range(N):
            if maps[i][j]>=2 and not ((i,j) in move_goorm):
                goorm.append((i,j))
                maps[i][j]-=2
 
answer = 0
for map_ in maps:
    answer += sum(map_)
print(answer)
 
 
 
cs

문제링크:

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

 

21610번: 마법사 상어와 비바라기

마법사 상어는 파이어볼, 토네이도, 파이어스톰, 물복사버그 마법을 할 수 있다. 오늘 새로 배운 마법은 비바라기이다. 비바라기를 시전하면 하늘에 비구름을 만들 수 있다. 오늘은 비바라기

www.acmicpc.net

 

728x90
반응형

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

[BOJ]2631. 줄세우기  (0) 2022.02.08
[BOJ] 9576. 책 나눠주기  (0) 2022.02.07
[BOJ]20057. 마법사 상어와 토네이도  (0) 2021.11.04
[BOJ] 15685. 드래곤 커브  (0) 2021.11.03
[BOJ]20056. 마법사 상어와 파이어볼  (0) 2021.11.02
728x90
반응형

문제:

마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을 의미한다.

토네이도를 시전하면 격자의 가운데 칸부터 토네이도의 이동이 시작된다. 토네이도는 한 번에 한 칸 이동한다. 다음은 N = 7인 경우 토네이도의 이동이다.

토네이도가 한 칸 이동할 때마다 모래는 다음과 같이 일정한 비율로 흩날리게 된다.

토네이도가 x에서 y로 이동하면, y의 모든 모래가 비율과 α가 적혀있는 칸으로 이동한다. 비율이 적혀있는 칸으로 이동하는 모래의 양은 y에 있는 모래의 해당 비율만큼이고, 계산에서 소수점 아래는 버린다. α로 이동하는 모래의 양은 비율이 적혀있는 칸으로 이동하지 않은 남은 모래의 양과 같다. 모래가 이미 있는 칸으로 모래가 이동하면, 모래의 양은 더해진다. 위의 그림은 토네이도가 왼쪽으로 이동할 때이고, 다른 방향으로 이동하는 경우는 위의 그림을 해당 방향으로 회전하면 된다.

토네이도는 (1, 1)까지 이동한 뒤 소멸한다. 모래가 격자의 밖으로 이동할 수도 있다. 토네이도가 소멸되었을 때, 격자의 밖으로 나간 모래의 양을 구해보자.

입력:

첫째 줄에 격자의 크기 N이 주어진다. 둘째 줄부터 N개의 줄에는 격자의 각 칸에 있는 모래가 주어진다. r번째 줄에서 c번째 주어지는 정수는 A[r][c] 이다.

출력:

격자의 밖으로 나간 모래의 양을 출력한다.

풀이방법:

 이 문제의 핵심은 회오리 모양으로 토네이도가 이동하는 것을 구현, 토네이도가 이동함에 따라 모래가 흩날리는 것을 구현해야 한다.

 

우선 회오리 모양으로 이동하는 것은 다음과 같은 규칙이 있다.

 

1) 방향은 좌, 하, 우, 상 을 반복하며 진행된다.

  - 따라서 dx, dy를 +1할 때마다 방향이 좌, 하, 우, 상으로 바뀌게 설정한다.

2) 좌, 하, 우, 상으로 이동할 때 거리는 1, 1, 2, 2, 3, 3, 4, 4, .... 와 같이 매 짝수 인덱스마다 증가하게 된다.

  - 다만 맨 마지막은 N-1, N-1, N, N, N 과 같이 N이 3번 반복되며 끝난다.

 

따라서 1), 2)의 조건을 만족하며 토네이도를 이동시키고, 토네이도가 0,0에 도달하면 이동을 종료하도록 한다. (소멸)

 

 모래가 흩날리는 것은 spread라는 배열을 만들어서 해결한다. 모래가 흩날리는 것은 좌, 하, 우, 상에 따라 흩날리는 위치가 다르기 때문에 방향 인덱스에 따라 모래의 이동 인덱스를 정리해둔다. 그리고 해당 인덱스에 따라 모래가 이동할 양인 ratio를 설정하도록 한다. 이 때, a의 경우에는 ratio를 0으로 설정한 뒤 따로 설정하도록 한다. 

 global 변수 answer를 설정하고, 범위 밖으로 나가는 모래는 다 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
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
dx = [0,1,0,-1]
dy = [-1,0,1,0]
spread = [
    [(0,-2),(-1,-1),(1,-1),(-1,0),(1,0),(-2,0),(2,0),(-1,1),(1,1),(0,-1)],
    [(2,0),(1,-1),(1,1),(0,-1),(0,1),(0,-2),(0,2),(-1,-1),(-1,1),(1,0)],
    [(0,2),(-1,1),(1,1),(-1,0),(1,0),(-2,0),(2,0),(-1,-1),(1,-1),(0,1)],
    [(-2,0),(-1,1),(-1,-1),(0,1),(0,-1),(0,2),(0,-2),(1,1),(1,-1),(-1,0)]
]
ratio = [0.05,0.1,0.1,0.07,0.07,0.02,0.02,0.01,0.01,0]
 
def spread_sand(total, d):
    global answer
    now = spread[d]
    remain = 0
    for (x,y), rt in zip(now, ratio):
        if rt==0:
            sand = total-remain
        else:
            sand = int(total * rt)
            remain+=sand
        if 0 <= r+< N and 0 <= c+< N:
            maps[r+x][c+y] += sand
        else:
            answer += sand
    maps[r][c] = 0
 
= int(input())
 
maps = []
for _ in range(N):
    maps.append(list(map(int,input().split())))
 
r, c = N//2, N//2
idx = 0
= 0
length = 1
answer = 0
while True:
    if idx==0:
        pass
    elif idx%2==0:
        length+=1
        if length==N:
            length-=1
    if r==0 and c==0:
        break
    for _ in range(length):
        r = r + dx[d]
        c = c + dy[d]
        total = maps[r][c]
        spread_sand(total, d)
    d = (d+1)%4
    idx+=1
 
print(answer)
cs

 

문제링크:

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

 

20057번: 마법사 상어와 토네이도

마법사 상어가 토네이도를 배웠고, 오늘은 토네이도를 크기가 N×N인 격자로 나누어진 모래밭에서 연습하려고 한다. 위치 (r, c)는 격자의 r행 c열을 의미하고, A[r][c]는 (r, c)에 있는 모래의 양을

www.acmicpc.net

 

728x90
반응형

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

[BOJ] 9576. 책 나눠주기  (0) 2022.02.07
[BOJ]21610. 마법사 상어와 비바라기  (0) 2021.11.05
[BOJ] 15685. 드래곤 커브  (0) 2021.11.03
[BOJ]20056. 마법사 상어와 파이어볼  (0) 2021.11.02
[BOJ]11058. 크리보드  (0) 2021.11.01
728x90
반응형

문제:

드래곤 커브는 다음과 같은 세 가지 속성으로 이루어져 있으며, 이차원 좌표 평면 위에서 정의된다. 좌표 평면의 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인 정사각형의 네 꼭짓점이 모두 드래곤 커브의 일부인 것의 개수를 출력한다.

풀이방법:

 시작점으로부터 드래곤 커브들의 방향을 구한 뒤에 모든 세대에 대한 점을 기록하는 방식으로 진행한다. 드래곤 커브를 만들 때 하나의 규칙은 N세대의 드래곤 커브를 만들기 위해 N-1세대의 끝 부터 시계 반대방향으로 90도를 회전시키면서 이어붙이면 처음부터 끝까지 한 배열에서 이어지게 만들 수 있다. 따라서 이전 세대의 끝부터 다음 세대를 진행시키도록 한다.

 모든 드래곤 커브를 그린 뒤에 100x100를 모두 탐색하며 각 꼭짓점이 모두 1인 경우만 +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
dx = [10-10]
dy = [0-101]
 
= int(input())
 
maps = [[0 for _ in range(101)] for _ in range(101)]
for _ in range(N):
    x, y, d, g = map(int, input().split())
    maps[x][y] = 1
    move = [d]
    for _ in range(g):
        temp = []
        for i in range(len(move)-1,-1,-1):
            temp.append((move[i]+1)%4)
        move.extend(temp)
 
    for m in move:
        x = x + dx[m]
        y = y + dy[m]
        maps[x][y] = 1
 
answer = 0
for i in range(100):
    for j in range(100):
        if maps[i][j]:
            if maps[i+1][j] and maps[i][j+1and maps[i+1][j+1]:
                answer += 1
print(answer)
cs

문제링크:

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

 

15685번: 드래곤 커브

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

www.acmicpc.net

 

728x90
반응형
728x90
반응형

문제:

어른 상어가 마법사가 되었고, 파이어볼을 배웠다.

마법사 상어가 크기가 N×N인 격자에 파이어볼 M개를 발사했다. 가장 처음에 파이어볼은 각자 위치에서 이동을 대기하고 있다. i번 파이어볼의 위치는 (ri, ci), 질량은 mi이고, 방향은 di, 속력은 si이다. 위치 (r, c)는 r행 c열을 의미한다.

격자의 행과 열은 1번부터 N번까지 번호가 매겨져 있고, 1번 행은 N번과 연결되어 있고, 1번 열은 N번 열과 연결되어 있다.

파이어볼의 방향은 어떤 칸과 인접한 8개의 칸의 방향을 의미하며, 정수로는 다음과 같다.

7 0 1
6   2
5 4 3

마법사 상어가 모든 파이어볼에게 이동을 명령하면 다음이 일들이 일어난다.

  1. 모든 파이어볼이 자신의 방향 di로 속력 si칸 만큼 이동한다.
    • 이동하는 중에는 같은 칸에 여러 개의 파이어볼이 있을 수도 있다.
  2. 이동이 모두 끝난 뒤, 2개 이상의 파이어볼이 있는 칸에서는 다음과 같은 일이 일어난다.
    1. 같은 칸에 있는 파이어볼은 모두 하나로 합쳐진다.
    2. 파이어볼은 4개의 파이어볼로 나누어진다.
    3. 나누어진 파이어볼의 질량, 속력, 방향은 다음과 같다.
      1. 질량은 ⌊(합쳐진 파이어볼 질량의 합)/5⌋이다.
      2. 속력은 ⌊(합쳐진 파이어볼 속력의 합)/(합쳐진 파이어볼의 개수)⌋이다.
      3. 합쳐지는 파이어볼의 방향이 모두 홀수이거나 모두 짝수이면, 방향은 0, 2, 4, 6이 되고, 그렇지 않으면 1, 3, 5, 7이 된다.
    4. 질량이 0인 파이어볼은 소멸되어 없어진다.

마법사 상어가 이동을 K번 명령한 후, 남아있는 파이어볼 질량의 합을 구해보자.

입력:

첫째 줄에 N, M, K가 주어진다.

둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다.

서로 다른 두 파이어볼의 위치가 같은 경우는 입력으로 주어지지 않는다.

출력:

마법사 상어가 이동을 K번 명령한 후, 남아있는 파이어볼 질량의 합을 출력한다.

풀이방법:

 주어진 조건대로 구현을 수행하도록 한다. 한 칸에는 여러 개의 파이어볼이 존재할 수 있기 때문에 deque로 구성되어 있는 maps을 구성하도록 한다. 주어진 입력을 모두 정리한 뒤에 K번 이동을 시작한다.

 maps를 모두 탐색하면서 하나의 파이어볼이라도 있다면 이동 명령을 수행한다. 이 때, 벽을 만나더라도 1행-N행, 1열-N열은 모두 연결되어 있기 때문에 %명령어로 이를 해결하도록 한다.

 모든 파이어볼 이동이 끝난 뒤에 다시 한번 maps를 모두 탐색하도록 한다. 이번에는 파이어볼이 2개 이상 있는 칸을 탐색하며 해당 칸에 대해 합치고 분배되는 명령을 수행하도록 한다.

 두 명령을 K번 수행한 후, maps에 남은 파이어볼의 질량을 모두 합하도록 한다.

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
from collections import deque
import copy
 
dx = [-1,-1,0,1,1,1,0,-1]
dy = [0,1,1,1,0,-1,-1,-1]
 
def main():
    N, M, K = map(int,input().split())
    maps = [[deque() for _ in range(N)] for _ in range(N)]
 
    for _ in range(M):
        r, c, m, s, d = map(int, input().split())
        if m!=0:
            maps[r-1][c-1].append([m,s,d])
 
    while K:
        temp = [[deque() for _ in range(N)] for _ in range(N)]
        for i in range(N):
            for j in range(N):
                if maps[i][j]:
                    while maps[i][j]:
                        m, s, d = maps[i][j].popleft()
                        nx = i + dx[d]*s
                        ny = j + dy[d]*s
                        nx = (nx + N) % N
                        ny = (ny + N) % N
                        temp[nx][ny].append([m, s, d])
 
        for i in range(N):
            for j in range(N):
                if len(temp[i][j]) > 1:
                    nm, ns, nd = 00, []
                    for m, s, d in temp[i][j]:
                        nm += m
                        ns += s
                        nd.append(d%2)
                    nm = int(nm/5)
                    if nm == 0:
                        temp[i][j] = deque()
                        continue
                    ns = int(ns/len(temp[i][j]))
                    temp[i][j] = deque()
                    if list(set(nd)) == [1or list(set(nd)) == [0]:
                        nd = [0246]
                    else:
                        nd = [1357]
                    for d in range(4):
                        temp[i][j].append([nm, ns, nd[d]])
        maps = copy.deepcopy(temp)
        K -= 1
 
    answer = 0
    for i in range(N):
        for j in range(N):
            if maps[i][j]:
                while maps[i][j]:
                    m, _, _ = maps[i][j].popleft()
                    answer += m
    print(answer)
 
if  __name__ == '__main__':
    main()
cs

문제링크:

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

 

20056번: 마법사 상어와 파이어볼

첫째 줄에 N, M, K가 주어진다. 둘째 줄부터 M개의 줄에 파이어볼의 정보가 한 줄에 하나씩 주어진다. 파이어볼의 정보는 다섯 정수 ri, ci, mi, si, di로 이루어져 있다. 서로 다른 두 파이어볼의 위치

www.acmicpc.net

 

728x90
반응형

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

[BOJ]20057. 마법사 상어와 토네이도  (0) 2021.11.04
[BOJ] 15685. 드래곤 커브  (0) 2021.11.03
[BOJ]11058. 크리보드  (0) 2021.11.01
[BOJ]14391. 종이 조각  (0) 2021.10.29
[BOJ] 2251. 물통  (0) 2021.10.28
728x90
반응형

문제:

크리보드는 kriii가 만든 신기한 키보드이다. 크리보드에는 버튼이 4개만 있으며, 하는 역할은 다음과 같다.

  1. 화면에 A를 출력한다.
  2. Ctrl-A: 화면을 전체 선택한다
  3. Ctrl-C: 전체 선택한 내용을 버퍼에 복사한다
  4. Ctrl-V: 버퍼가 비어있지 않은 경우에는 화면에 출력된 문자열의 바로 뒤에 버퍼의 내용을 붙여넣는다.

크리보드의 버튼을 총 N번 눌러서 화면에 출력된 A개수를 최대로하는 프로그램을 작성하시오.

입력:

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

출력:

크리보드의 버튼을 총 N번 눌러서 화면에 출력할 수 있는 A 개수의 최댓값을 출력한다.

풀이방법:

DP를 사용해서 해당문제를 풀도록 한다. 이 때, N이 6번까지는 ctrl+A,C,V를 사용하는 것보다 하나를 더 추가하는 것이 더 이득이기 때문에 하나씩 추가하도록 한다. 복사 붙여넣기를 하기 위해서는 최소 3개의 명령어를 사용해야 한다. 따라서 ACV, ACVV, ACVVV, ...와 같은 방법으로 붙여넣기를 진행할 수 있다. 하지만 붙여넣기는 최대 3번만 사용해도 최댓값을 구할 수 있기 때문에 ACV, ACVV, ACVVV 와 같은 3개 경우에 대해서 DP를 진행하도록 한다.

점화식은 dp[i] = max(dp[i-3-j]*(2*j), dp[i])와 같다.

1
2
3
4
5
6
7
8
9
10
11
= int(input())
 
dp = [0* 101
 
for i in range(1,7):
    dp[i]=i
    
for i in range(7, N+1):
    for j in range(3):
        dp[i] = max(dp[i-3-j]*(2+j),dp[i])
print(dp[N])
cs

문제링크:

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

 

11058번: 크리보드

N = 3인 경우에 A, A, A를 눌러 A 3개를 출력할 수 있다. N = 7인 경우에는 A, A, A, Ctrl-A, Ctrl-C, Ctrl-V, Ctrl-V를 눌러 9개를 출력할 수 있다. N = 11인 경우에는 A, A, A, Ctrl-A, Ctrl-C, Ctrl-V, Ctrl-V, Ctrl-A, Ctrl-C, Ctrl

www.acmicpc.net

 

728x90
반응형

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

[BOJ] 15685. 드래곤 커브  (0) 2021.11.03
[BOJ]20056. 마법사 상어와 파이어볼  (0) 2021.11.02
[BOJ]14391. 종이 조각  (0) 2021.10.29
[BOJ] 2251. 물통  (0) 2021.10.28
[BOJ] 15988. 1, 2, 3 더하기  (0) 2021.10.25
728x90
반응형

문제:

영선이는 숫자가 쓰여 있는 직사각형 종이를 가지고 있다. 종이는 1×1 크기의 정사각형 칸으로 나누어져 있고, 숫자는 각 칸에 하나씩 쓰여 있다. 행은 위에서부터 아래까지 번호가 매겨져 있고, 열은 왼쪽부터 오른쪽까지 번호가 매겨져 있다.

영선이는 직사각형을 겹치지 않는 조각으로 자르려고 한다. 각 조각은 크기가 세로나 가로 크기가 1인 직사각형 모양이다. 길이가 N인 조각은 N자리 수로 나타낼 수 있다. 가로 조각은 왼쪽부터 오른쪽까지 수를 이어 붙인 것이고, 세로 조각은 위에서부터 아래까지 수를 이어붙인 것이다.

아래 그림은 4×4 크기의 종이를 자른 한 가지 방법이다.

각 조각의 합은 493 + 7160 + 23 + 58 + 9 + 45 + 91 = 7879 이다.

종이를 적절히 잘라서 조각의 합을 최대로 하는 프로그램을 작성하시오.

입력:

첫째 줄에 종이 조각의 세로 크기 N과 가로 크기 M이 주어진다. (1 ≤ N, M ≤ 4)

둘째 줄부터 종이 조각이 주어진다. 각 칸에 쓰여 있는 숫자는 0부터 9까지 중 하나이다.

출력:

영선이가 얻을 수 있는 점수의 최댓값을 출력한다.

풀이방법:

 비트마스킹을 사용하여 해당 문제를 풀었다. N*M의 크기의 직사각형을 0,1의 비트마스킹으로 표현한다. 이 때 0은 가로로 연결되는 경우를 의미하고, 1은 세로로 연결되는 경우를 의미하게 된다.

 주어진 케이스에 대해 가로와 각각 따로 계산을 수행하도록 한다. 가로는 idx가 0인 경우에 대해서만 이어붙이며 값을 누적시키도록 한다. 반대로 세로는 idx가 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
34
35
36
37
from itertools import product
 
h, w = map(int, input().split())
mat = []
for i in range(h):
    mat.append(list(map(int,list(input()))))
 
idxs = product(range(2),repeat=h*w)
 
ans = 0
for idx in idxs:
    tmp = 0
    for i in range(h):
        sum_ = 0
        for j in range(w):
            k = i*w+j
            if idx[k]==0:
                sum_ = 10*sum_+mat[i][j]
            else:
                tmp+=sum_
                sum_ = 0
        if sum_!=0:
            tmp+=sum_
    for i in range(w):
        sum_ = 0
        for j in range(h):
            k = i+j*w
            if idx[k]==1:
                sum_ = 10*sum_+mat[j][i]
            else:
                tmp+=sum_
                sum_ = 0
        if sum_!=0:
            tmp+=sum_
    if tmp > ans:
        ans = tmp
print(ans)
cs

문제링크:

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

 

14391번: 종이 조각

영선이는 숫자가 쓰여 있는 직사각형 종이를 가지고 있다. 종이는 1×1 크기의 정사각형 칸으로 나누어져 있고, 숫자는 각 칸에 하나씩 쓰여 있다. 행은 위에서부터 아래까지 번호가 매겨져 있고,

www.acmicpc.net

 

728x90
반응형

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

[BOJ]20056. 마법사 상어와 파이어볼  (0) 2021.11.02
[BOJ]11058. 크리보드  (0) 2021.11.01
[BOJ] 2251. 물통  (0) 2021.10.28
[BOJ] 15988. 1, 2, 3 더하기  (0) 2021.10.25
[BOJ] 13023. ABCDE  (0) 2021.10.22
728x90
반응형

문제:

각각 부피가 A, B, C(1≤A, B, C≤200) 리터인 세 개의 물통이 있다. 처음에는 앞의 두 물통은 비어 있고, 세 번째 물통은 가득(C 리터) 차 있다. 이제 어떤 물통에 들어있는 물을 다른 물통으로 쏟아 부을 수 있는데, 이때에는 한 물통이 비거나, 다른 한 물통이 가득 찰 때까지 물을 부을 수 있다. 이 과정에서 손실되는 물은 없다고 가정한다.

이와 같은 과정을 거치다보면 세 번째 물통(용량이 C인)에 담겨있는 물의 양이 변할 수도 있다. 첫 번째 물통(용량이 A인)이 비어 있을 때, 세 번째 물통(용량이 C인)에 담겨있을 수 있는 물의 양을 모두 구해내는 프로그램을 작성하시오.

입력:

첫째 줄에 세 정수 A, B, C가 주어진다.

출력:

첫째 줄에 공백으로 구분하여 답을 출력한다. 각 용량은 오름차순으로 정렬한다.

풀이방법:

A, B를 담을 수 있는 물통들을 기준으로 하여 visited 배열을 만들고, BFS를 수행하도록 한다. visited의 가능한 갯수는 A와 B에 담을 수 있는 경우의 수와 같다. 처음은 비어있기 때문에, (0,0)으로부터 시작하도록 한다. 매 C는 가지고 있는 A, B 물의 양을 통해 구하도록 한다. 가지고 있는 A, B, C 물의 양을 통해 이동할 수 있는 모든 경우에 대해 조사하도록 한다. (A-> B, A-> C, B->C, B-> A, C-> A, C-> B)와 같은 총 6가지 case가 존재한다. 가능한 모든 경우에 대해 BFS를 수행하며 A의 물의 양이 0인 경우에 C의 값을 저장하도록 한다.

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
from collections import deque
 
A, B, C = map(int,input().split())
 
queue = deque()
queue.append((0,0))
visited = [[0 for _ in range(B+1)] for _ in range(A+1)]
visited[0][0= 1
 
answer = []
while queue:
    x,y = queue.popleft()
    z = C-x-y
    if x==0:
        answer.append(z)
    
    #A->B
    water = min(x,B-y)
    if not visited[x-water][y+water]:
        visited[x-water][y+water] = 1
        queue.append((x-water,y+water))
    
    #A->C
    water = min(x,C-z)
    if not visited[x-water][y]:
        visited[x-water][y] = 1
        queue.append((x-water,y))
        
    #B->C
    water = min(y,C-z)
    if not visited[x][y-water]:
        visited[x][y-water] = 1
        queue.append((x,y-water))
        
    #B->A
    water = min(y,A-x)
    if not visited[x+water][y-water]:
        visited[x+water][y-water] = 1
        queue.append((x+water,y-water))
        
    #C->A
    water = min(z,A-x)
    if not visited[x+water][y]:
        visited[x+water][y] = 1
        queue.append((x+water,y))
 
    #C->B
    water = min(z,B-y)
    if not visited[x][y+water]:
        visited[x][y+water] = 1
        queue.append((x,y+water))
    
print(*sorted(answer))
cs

문제링크:

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

 

2251번: 물통

각각 부피가 A, B, C(1≤A, B, C≤200) 리터인 세 개의 물통이 있다. 처음에는 앞의 두 물통은 비어 있고, 세 번째 물통은 가득(C 리터) 차 있다. 이제 어떤 물통에 들어있는 물을 다른 물통으로 쏟아 부

www.acmicpc.net

 

728x90
반응형

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

[BOJ]11058. 크리보드  (0) 2021.11.01
[BOJ]14391. 종이 조각  (0) 2021.10.29
[BOJ] 15988. 1, 2, 3 더하기  (0) 2021.10.25
[BOJ] 13023. ABCDE  (0) 2021.10.22
[BOJ]1339. 단어 수학  (0) 2021.10.21
728x90
반응형

문제:

정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 7가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다.

  • 1+1+1+1
  • 1+1+2
  • 1+2+1
  • 2+1+1
  • 2+2
  • 1+3
  • 3+1

정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.

입력:

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 1,000,000보다 작거나 같다.

출력:

각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.

풀이방법:

 이전 1, 2, 3 더하기 문제에서는 재귀형태로 문제를 풀었지만 이번에는 숫자의 범위가 크기 때문에 시간초과가 발생할 것이다. 따라서 이번에는 dp 배열을 사용하여 문제를 풀도록 한다. 

 점화식은 간단한 편이다. N을 만들기 위해서 N-3의 경우에서 3을 N-2의 경우에서 2를 N-1일 대는 1을 각각 더해주면 되기 때문이다. 즉, dp[N] = dp[N-1] + dp[N-2] + dp[N-3]과 같다.

1000000까지 dp를 만든 뒤에 N 값을 출력하도록 한다.

1
2
3
4
5
6
7
8
= int(input())
dp = [0]*1000001
dp[1],dp[2],dp[3= 1,2,4
for i in range(4,1000001):
    dp[i] = (dp[i-1]+dp[i-2]+dp[i-3])%1000000009
for _ in range(T):
    n = int(input())
    print(dp[n])
cs

문제링크:

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

 

15988번: 1, 2, 3 더하기 3

각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.

www.acmicpc.net

 

728x90
반응형

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

[BOJ]14391. 종이 조각  (0) 2021.10.29
[BOJ] 2251. 물통  (0) 2021.10.28
[BOJ] 13023. ABCDE  (0) 2021.10.22
[BOJ]1339. 단어 수학  (0) 2021.10.21
[BOJ] 15658. 연산자 끼워넣기 (2)  (0) 2021.10.20

+ Recent posts