백준
[BOJ] BOJ 32114번 'SoleMap' (Java)
MoveForward
2025. 2. 2. 22:54
[문제]
https://www.acmicpc.net/problem/32114
[접근방식]
도시와 도시 사이에 위치한 각 도로의 '도로 부담' 지수를 구하는 문제이다.
1. '차량 정보'를 이용하여 각 도로 구간 별 일일 차량 통행량을 구한다.
2. 각 도로 구간의 차선 개수에 따라 일일 차량 통행량을 최대한 고르게 분배한다.
1번과 2번을 구현하는 방식은 크게 어렵지 않았다.
그러나 1번을 단순 구현을 한다면 "시간초과" 에 걸릴 수 있다.
※ 배열의 인덱스 편의상 도시의 명칭은 0 부터 N - 1까지 지정한다.
1. 단순 누적합 구하기
// 차량 정보 처리
long[] vehicleCount = new long[N]; // 구간 별 차량 수 누적
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken()) - 1; // 도시 인덱스 0-based
int v = Integer.parseInt(st.nextToken()) - 1;
int x = Integer.parseInt(st.nextToken());
for (int a = u; a < v; a++) {
vehicleCount[a] += x;
}
}
단순 누적합을 구하는 방식은 u 구역 부터 v-1 구역까지 반복문을 통해 통행량을 누적하여 계산한다.
2. 증감을 이용한 누적합 구하기
// 차량 정보 처리
long[] vehicleCount = new long[N]; // 차량 수 누적
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken()) - 1; // 도시 인덱스 0-based
int v = Integer.parseInt(st.nextToken()) - 1;
int x = Integer.parseInt(st.nextToken());
vehicleCount[u] += x; // 구간 시작에 차량 수 추가
if (v < N) vehicleCount[v] -= x; // 구간 끝 뒤에 차량 수 빼기
}
// 차량 수를 구간별로 누적
for (int i = 1; i < N; i++) {
vehicleCount[i] += vehicleCount[i - 1];
}
전 인덱스의 값을 이용하여 해당값으로 부터의 증감값을 이용하여 통행량을 계산한다.
이 방식은 한번의 반복문을 통해 통행량 계산을 완료할 수 있다.
[Java 코드]
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
// 도시의 수 N, 차량 정보의 수 M
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
// 각 도로의 차선 수 w[i]
int[] w = new int[N - 1];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < N - 1; i++) {
w[i] = Integer.parseInt(st.nextToken());
}
// 차량 정보 처리
long[] vehicleCount = new long[N]; // 차량 수 누적
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken()) - 1; // 도시 인덱스 0-based
int v = Integer.parseInt(st.nextToken()) - 1;
int x = Integer.parseInt(st.nextToken());
vehicleCount[u] += x; // 구간 시작에 차량 수 추가
if (v < N) vehicleCount[v] -= x; // 구간 끝 뒤에 차량 수 빼기
}
// 차량 수를 구간별로 누적
for (int i = 1; i < N; i++) {
vehicleCount[i] += vehicleCount[i - 1];
}
// 도로 부담 계산
StringBuilder sb = new StringBuilder();
for (int i = 0; i < N - 1; i++) {
long c = vehicleCount[i]; // 도로에 지나가는 차량 수
int lanes = w[i]; // 차선 수
// 차량 c 대를 lanes 개 차선에 분배
long quotient = c / lanes; // 각 차선에 기본적으로 할당되는 차량 수
long remainder = c % lanes; // 나머지 차량 수
// 분배된 차량 수에 대한 제곱합 최소화
// remainder 차선에는 (quotient + 1) 대, 나머지 차선에는 quotient 대를 할당
long weight = remainder * (quotient + 1) * (quotient + 1) + (lanes - remainder) * quotient * quotient;
sb.append(weight).append("\n");
}
System.out.print(sb);
}
}