행성들을 침략, 동원하여 모든 행성을 정복하려한다. 함선의 갯수보다 인구수가 적은 곳을 침략하여 주민들의 수를 흡수할 수 있다. 동원은 주민들의 수 만큼 함선을 만들 수 있다. 한 행성 당 1번의 동원을 할 수 있을 때, 최소 동원 횟수를 구하는 문제이다. 모든 행성을 정복할 수 없으면 -1을 출력한다.
모든 행성들의 인구들을 합해 둔 후, 행성들을 정복하면서 현재 인구수 보다 작게 되면 동원을 종료하고 남은 행성들을 침략하면 된다. 현재 정복 가능한 가장 큰 행성을 침략 후 동원하여 주민들의 수를 최대화해야 최소한의 동원 횟수로 모든 행성을 정복할 수 있다. 이를 위해 배열에 행성들의 인구수를 넣은 후 정렬하였다.
long[] board = new long[n];
boolean[] visited = new boolean[n];
for(int i=0; i<n; i++) {
long num = Long.parseLong(st.nextToken());
sum += num;
board[i] = num;
}
Arrays.sort(board);
이후, 배열의 맨 앞부터 끝까지 현재 인구수보다 작거나 같은 가장 큰 행성을 정복한 후, 동원한다. 정복하면서 인구수가 남은 행성 수 보다 크거나 같으면 침략만 하면 되므로 횟수를 세지 않고 종료한다. 현재 인구수로 정복할 수 있는 행성이 없다면 정복하지 않은 이전 행성들을 전부 정복하면서 큰 행성을 정복할 수 있을 때 까지 정복한다. 그래도 불가능할 경우, 모든 행성을 정복할 수 없게 되므로 -1을 출력한다. 또한, 최적화를 통해 마지막 행성을 정복했음에도 인구수가 나머지 행성들의 합 보다 작은 경우, 동원 횟수가 필요하므로 인구수가 나머지 행성들의 합보다 크거나 같을 때 까지 남은 가장 큰 행성들을 정복한다.
int count = 0;
for(int i=0; i<n; i++) {
if(k >= sum) break;
if(i == n-1 && k >= board[i]) {
for(int j=i; j>=0; j--) {
if(visited[j]) continue;
visited[j] = true;
sum -= board[j];
k += board[j];
count++;
if(k < sum) continue;
else break;
}
if(k < sum) {
sb.append("-1").append('\n');
continue out;
}
sb.append(count).append('\n');
continue out;
} else if(board[i] > k) {
while(board[i] > k) {
for(int j=i-1; j>=0; j--) {
if(visited[j]) continue;
if(board[j] > k) continue;
visited[j] = true;
sum -= board[j];
k += board[j];
count++;
if(board[i] > k) continue;
else break;
}
if(board[i] > k) {
sb.append("-1").append('\n');
continue out;
}
if(k < sum) {
if(i == n-1) {
for(int j=i; j>=0; j--) {
if(visited[j]) continue;
visited[j] = true;
sum -= board[j];
k += board[j];
count++;
if(k < sum) continue;
else break;
}
if(k < sum) {
sb.append("-1").append('\n');
continue out;
}
sb.append(count).append('\n');
continue out;
}
} else {
sb.append(count).append('\n');
continue out;
}
}
}
}
sb.append(count).append('\n');
결과 코드는 다음과 같다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Solution {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int T = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
out: for (int tc = 1; tc <= T; tc++) {
sb.append('#').append(tc).append(' ');
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
long k = Long.parseLong(st.nextToken());
long sum = 0L;
st = new StringTokenizer(br.readLine());
long[] board = new long[n];
boolean[] visited = new boolean[n];
for(int i=0; i<n; i++) {
long num = Long.parseLong(st.nextToken());
sum += num;
board[i] = num;
}
Arrays.sort(board);
int count = 0;
for(int i=0; i<n; i++) {
if(k >= sum) break;
if(i == n-1 && k >= board[i]) {
for(int j=i; j>=0; j--) {
if(visited[j]) continue;
visited[j] = true;
sum -= board[j];
k += board[j];
count++;
if(k < sum) continue;
else break;
}
if(k < sum) {
sb.append("-1").append('\n');
continue out;
}
sb.append(count).append('\n');
continue out;
} else if(board[i] > k) {
while(board[i] > k) {
for(int j=i-1; j>=0; j--) {
if(visited[j]) continue;
if(board[j] > k) continue;
visited[j] = true;
sum -= board[j];
k += board[j];
count++;
if(board[i] > k) continue;
else break;
}
if(board[i] > k) {
sb.append("-1").append('\n');
continue out;
}
if(k < sum) {
if(i == n-1) {
for(int j=i; j>=0; j--) {
if(visited[j]) continue;
visited[j] = true;
sum -= board[j];
k += board[j];
count++;
if(k < sum) continue;
else break;
}
if(k < sum) {
sb.append("-1").append('\n');
continue out;
}
sb.append(count).append('\n');
continue out;
}
} else {
sb.append(count).append('\n');
continue out;
}
}
}
}
sb.append(count).append('\n');
}
br.close();
System.out.print(sb);
}
}'알고리즘(백준 등) 공부' 카테고리의 다른 글
| SWEA 15612. 체스판 위의 룩 배치 (0) | 2026.05.08 |
|---|---|
| SWEA 15758. 무한 문자열 (0) | 2026.05.07 |
| SWEA 16002. 합성수 방정식 (0) | 2026.05.05 |
| SWEA 16003. 화면 캡쳐 (0) | 2026.05.05 |
| SWEA 16800. 구구단 걷기 (0) | 2026.05.04 |