Skip to content

Commit 74aae1e

Browse files
committed
[Gold III] Title: 백준 빙고 스피드러너, Time: 812 ms, Memory: 295540 KB -BaekjoonHub
1 parent 1732f14 commit 74aae1e

2 files changed

Lines changed: 283 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# [Gold III] 백준 빙고 스피드러너 - 34753
2+
3+
[문제 링크](https://www.acmicpc.net/problem/34753)
4+
5+
### 성능 요약
6+
7+
메모리: 295540 KB, 시간: 812 ms
8+
9+
### 분류
10+
11+
구현, 시뮬레이션
12+
13+
### 제출 일자
14+
15+
2026년 3월 29일 15:33:46
16+
17+
### 문제 설명
18+
19+
<p>영과일에서는 방학 동안 학회원들을 대상으로 백준 빙고 이벤트를 진행한다. 이벤트 참가자들에게는 칸마다 백준 문제가 하나씩 배정된 $5\times 5$ 격자 모양의 빙고판이 주어진다. 참가자들은 문제를 풀어서 빙고판의 칸을 색칠할 수 있고, 방학 기간이 끝날 때까지 일정 빙고 수 이상을 달성하면 추첨을 통해 상품을 받을 수 있다.</p>
20+
21+
<p>그런데 범수는 천천히 방학 동안 풀라고 주어진 빙고판을 이벤트 때마다 첫날에 스피드런해서 전부 채워버렸다.</p>
22+
23+
<p style="text-align:center"><img alt="" src="https://upload.acmicpc.net/70c8dd27-073c-4fce-988f-ee9b9e26c530/-/preview/" style="height: 256px; width: 664px;"></p>
24+
25+
<p style="text-align:center">백준 빙고 이벤트 첫날 랭킹에 보이는 모습.</p>
26+
27+
<p>이런 모습을 지켜보던 학회장은 범수에게 $N\times N$ 격자 모양의 빙고판을 새로 만들어 주었다.</p>
28+
29+
<p>$N\times N$ 격자 모양의 빙고판에서 빙고 줄은 $N$개의 행, $N$개의 열, 그리고 모서리에서 출발하는 대각선 $2$개로 총 $2N+2$개이다. 어떤 빙고 줄의 문제를 모두 풀면 그 줄은 완성되고, 완성된 빙고 줄이 $k$개일 때 이를 $k$빙고라고 부른다.</p>
30+
31+
<p>범수는 스피드러너답게 새로운 빙고판에서도 어김없이 바로 스피드런을 시작하려 한다. 범수가 새 빙고판의 $i$행 $j$열에 해당하는 문제를 푸는 데는 $A_{ij}$ 만큼의 시간이 걸린다. 이에 따라 범수는 다음과 같은 스피드런 전략을 사용하기로 했다.</p>
32+
33+
<ul>
34+
<li>아직 완성되지 않은 줄 중, 완성하기 위해 필요한 시간이 가장 적은 줄을 선택한다.
35+
<ul>
36+
<li>어떤 빙고 줄을 완성하기 위해 필요한 시간은 그 줄에 있는 아직 풀지 않은 문제를 푸는 시간의 총합과 같다.</li>
37+
</ul>
38+
</li>
39+
<li>만약 필요한 시간이 가장 적은 줄이 여러 개라면, 다음 우선순위에 따라 가장 먼저 만족하는 줄을 선택한다.
40+
<ol>
41+
<li>후보에 행이 있다면 그중 행 번호가 가장 작은 행을 선택한다.</li>
42+
<li>후보에 열이 있다면 그중 열 번호가 가장 작은 열을 선택한다.</li>
43+
<li>후보에 왼쪽 위에서 오른쪽 아래로 향하는 대각선이 있다면 그 줄을 선택한다.</li>
44+
<li>후보에 오른쪽 위에서 왼쪽 아래로 향하는 대각선이 있다면 그 줄을 선택한다.</li>
45+
</ol>
46+
</li>
47+
<li>선택한 줄에 남아 있는 풀지 않은 문제를 모두 푼다. 이때 문제는 어느 순서로 풀어도 상관없다.</li>
48+
<li>문제는 동시에 하나씩만 풀 수 있고, 문제를 푸는 사이 쉬는 시간은 필요하지 않다.</li>
49+
</ul>
50+
51+
<p>학회장은 새 빙고판에서 범수가 $k$빙고를 달성하는 데 시간이 얼마나 걸릴지 궁금해졌다. 모든 $k$에 대해 그 시간을 구하는 프로그램을 작성해 보자.</p>
52+
53+
### 입력
54+
55+
<p>첫 번째 줄에 빙고판의 크기를 나타내는 정수 $N$이 주어진다. $(1\le N\le 1\, 500)$</p>
56+
57+
<p>두 번째 줄부터 $N$개의 줄에 걸쳐 각 줄마다 $N$개의 정수가 공백으로 구분되어 주어진다. $i+1$번째 줄의 $j$번째 정수 $A_{ij}$는 범수가 빙고판의 $i$행 $j$열에 해당하는 문제를 푸는 데 걸리는 시간을 의미한다. $(1\le A_{ij}\le 10^{9})$</p>
58+
59+
### 출력
60+
61+
<p>$2N+2$개의 줄에 걸쳐 $k$번째 줄에 처음으로 $k$빙고 이상이 되었을 때 경과한 시간을 출력한다. $(1\le k\le 2N+2)$</p>
62+
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import Foundation
2+
3+
let input = FastInput()
4+
let N = input.readInt()
5+
6+
var A = Array(repeating: Array(repeating: Int64(0), count: N), count: N)
7+
8+
for i in 0..<N {
9+
for j in 0..<N {
10+
A[i][j] = Int64(input.readInt())
11+
}
12+
}
13+
14+
var row = Array(repeating: Int64(0), count: N)
15+
var col = Array(repeating: Int64(0), count: N)
16+
var diag = [Int64(0), Int64(0)]
17+
18+
for i in 0..<N {
19+
for j in 0..<N {
20+
let v = A[i][j]
21+
row[i] += v
22+
col[j] += v
23+
if i == j { diag[0] += v }
24+
if i + j == N - 1 { diag[1] += v }
25+
}
26+
}
27+
28+
var visited = Array(repeating: Array(repeating: false, count: N), count: N)
29+
30+
var usedRow = Array(repeating: false, count: N)
31+
var usedCol = Array(repeating: false, count: N)
32+
var usedDiag = [false, false]
33+
34+
var pq = MinHeap<Line>()
35+
36+
for i in 0..<N {
37+
pq.push(Line(cost: row[i], type: 0, idx: i))
38+
}
39+
for j in 0..<N {
40+
pq.push(Line(cost: col[j], type: 1, idx: j))
41+
}
42+
pq.push(Line(cost: diag[0], type: 2, idx: 0))
43+
pq.push(Line(cost: diag[1], type: 3, idx: 0))
44+
45+
var result: [Int64] = []
46+
var completed = 0
47+
var currentTime: Int64 = 0
48+
49+
while completed < 2 * N + 2 {
50+
guard let top = pq.pop() else { break }
51+
52+
let cost = top.cost
53+
let type = top.type
54+
let idx = top.idx
55+
56+
if type == 0 && usedRow[idx] { continue }
57+
if type == 1 && usedCol[idx] { continue }
58+
if type == 2 && usedDiag[0] { continue }
59+
if type == 3 && usedDiag[1] { continue }
60+
61+
if type == 0 && row[idx] != cost { continue }
62+
if type == 1 && col[idx] != cost { continue }
63+
if type == 2 && diag[0] != cost { continue }
64+
if type == 3 && diag[1] != cost { continue }
65+
66+
currentTime += cost
67+
68+
if type == 0 {
69+
usedRow[idx] = true
70+
let i = idx
71+
for j in 0..<N {
72+
if visited[i][j] { continue }
73+
visited[i][j] = true
74+
let v = A[i][j]
75+
76+
row[i] -= v
77+
col[j] -= v
78+
if i == j { diag[0] -= v }
79+
if i + j == N - 1 { diag[1] -= v }
80+
81+
pq.push(Line(cost: col[j], type: 1, idx: j))
82+
if i == j { pq.push(Line(cost: diag[0], type: 2, idx: 0)) }
83+
if i + j == N - 1 { pq.push(Line(cost: diag[1], type: 3, idx: 0)) }
84+
}
85+
} else if type == 1 {
86+
usedCol[idx] = true
87+
let j = idx
88+
for i in 0..<N {
89+
if visited[i][j] { continue }
90+
visited[i][j] = true
91+
let v = A[i][j]
92+
93+
row[i] -= v
94+
col[j] -= v
95+
if i == j { diag[0] -= v }
96+
if i + j == N - 1 { diag[1] -= v }
97+
98+
pq.push(Line(cost: row[i], type: 0, idx: i))
99+
if i == j { pq.push(Line(cost: diag[0], type: 2, idx: 0)) }
100+
if i + j == N - 1 { pq.push(Line(cost: diag[1], type: 3, idx: 0)) }
101+
}
102+
} else if type == 2 {
103+
usedDiag[0] = true
104+
for i in 0..<N {
105+
let j = i
106+
if visited[i][j] { continue }
107+
visited[i][j] = true
108+
let v = A[i][j]
109+
110+
row[i] -= v
111+
col[j] -= v
112+
diag[0] -= v
113+
if i + j == N - 1 { diag[1] -= v }
114+
115+
pq.push(Line(cost: row[i], type: 0, idx: i))
116+
pq.push(Line(cost: col[j], type: 1, idx: j))
117+
if i + j == N - 1 { pq.push(Line(cost: diag[1], type: 3, idx: 0)) }
118+
}
119+
} else {
120+
usedDiag[1] = true
121+
for i in 0..<N {
122+
let j = N - 1 - i
123+
if visited[i][j] { continue }
124+
visited[i][j] = true
125+
let v = A[i][j]
126+
127+
row[i] -= v
128+
col[j] -= v
129+
diag[1] -= v
130+
if i == j { diag[0] -= v }
131+
132+
pq.push(Line(cost: row[i], type: 0, idx: i))
133+
pq.push(Line(cost: col[j], type: 1, idx: j))
134+
if i == j { pq.push(Line(cost: diag[0], type: 2, idx: 0)) }
135+
}
136+
}
137+
138+
completed += 1
139+
result.append(currentTime)
140+
}
141+
142+
let output = result.map { String($0) }.joined(separator: "\n")
143+
print(output)
144+
145+
final class FastInput {
146+
private var data: [UInt8] = Array(FileHandle.standardInput.readDataToEndOfFile())
147+
private var idx: Int = 0
148+
149+
func readInt() -> Int {
150+
var sign = 1
151+
var num = 0
152+
153+
while data[idx] == 10 || data[idx] == 13 || data[idx] == 32 { idx += 1 }
154+
155+
if data[idx] == 45 {
156+
sign = -1
157+
idx += 1
158+
}
159+
160+
while data[idx] >= 48 {
161+
num = num * 10 + Int(data[idx] - 48)
162+
idx += 1
163+
}
164+
165+
return num * sign
166+
}
167+
}
168+
169+
struct Line: Comparable {
170+
let cost: Int64
171+
let type: Int // 0: row, 1: col, 2: diag1, 3: diag2
172+
let idx: Int
173+
174+
static func < (lhs: Line, rhs: Line) -> Bool {
175+
if lhs.cost != rhs.cost { return lhs.cost < rhs.cost }
176+
if lhs.type != rhs.type { return lhs.type < rhs.type }
177+
return lhs.idx < rhs.idx
178+
}
179+
}
180+
181+
// 최소 힙
182+
struct MinHeap<T: Comparable> {
183+
private var heap: [T] = []
184+
185+
var isEmpty: Bool { heap.isEmpty }
186+
187+
mutating func push(_ x: T) {
188+
heap.append(x)
189+
var i = heap.count - 1
190+
while i > 0 {
191+
let p = (i - 1) >> 1
192+
if heap[p] <= heap[i] { break }
193+
heap.swapAt(p, i)
194+
i = p
195+
}
196+
}
197+
198+
mutating func pop() -> T? {
199+
if heap.isEmpty { return nil }
200+
if heap.count == 1 { return heap.removeLast() }
201+
202+
let ret = heap[0]
203+
heap[0] = heap.removeLast()
204+
205+
var i = 0
206+
while true {
207+
let l = i * 2 + 1
208+
let r = i * 2 + 2
209+
var smallest = i
210+
211+
if l < heap.count && heap[l] < heap[smallest] { smallest = l }
212+
if r < heap.count && heap[r] < heap[smallest] { smallest = r }
213+
214+
if smallest == i { break }
215+
heap.swapAt(i, smallest)
216+
i = smallest
217+
}
218+
219+
return ret
220+
}
221+
}

0 commit comments

Comments
 (0)