2138 전구와 스위치
https://www.acmicpc.net/problem/2138
문제설명
각 스위치를 누르면 해당 스위치와 인접한 스위치(왼쪽, 오른쪽)가 모두 바뀐다.
주어진 두 가지 초기 상태(첫 번째 스위치 누름 여부에 따라)에서 각각의 경우에 대해
전구의 상태를 변경하여 목표 상태로 만드는 데 필요한 최소한의 스위치 누름 횟수를 구한다.
문제풀이
- 첫 번째 스위치를 눌렀을 때
- 첫 번째 스위치를 누르지 않았을 때
- 각 경우에 대해 스위치를 차례로 확인하며, 목표 상태와 다르면 현재 스위치와 인접한 스위치를 모두 뒤집는다.
- 첫 번째 경우에서는 첫 번째 스위치를 누른 상태로 초기화한다.
- 두 번째 경우에서는 첫 번째 스위치를 누르지 않은 상태로 초기화한다.
- 각 경우에 대해 현재 스위치와 목표 상태를 비교하고, 다르면 스위치를 뒤집는다.
- 모든 스위치를 검사한 후 마지막 스위치의 상태가 목표 상태와 일치하는지 확인한다.
- 두 경우 중 유효한 경우의 최소 누름 횟수를 출력다.
- 최종적으로 두 경우에서의 스위치 누름 횟수를 비교하여 최소 값을 구한다.
O(n) 시간복잡도
입력된 전구의 개수 n에 대해 두 번의 반복이 발생하므로 선형 시간복잡도가 소요된다.
전체코드
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 스위치의 개수
int n = Integer.parseInt(br.readLine());
int ans1 = 1, ans2 = 0, INF = 987654321;
// 현재 상태와 예상 상태를 읽음
String now = br.readLine();
String expect = br.readLine();
// 두 가지 경우의 현재 상태를 저장할 배열과 예상 상태를 저장할 배열
int[] now_arr_1 = new int[n];
int[] now_arr_2 = new int[n];
int[] expect_arr = new int[n];
// 입력 문자열을 기반으로 현재 상태와 예상 상태 배열을 초기화
for (int i = 0; i < n; i++) {
now_arr_1[i] = now.charAt(i) - '0'; // 첫 번째 경우의 현재 상태
now_arr_2[i] = now.charAt(i) - '0'; // 두 번째 경우의 현재 상태
expect_arr[i] = expect.charAt(i) - '0'; // 예상 상태
}
// 첫 번째 경우의 첫 번째와 두 번째 스위치를 뒤집음
now_arr_1[0] = 1 - now_arr_1[0];
now_arr_1[1] = 1 - now_arr_1[1];
// 스위치를 순회하며 상태를 확인
for (int i = 1; i < n; i++) {
// 첫 번째 경우에서 현재 스위치가 예상 상태와 다르면
if (now_arr_1[i - 1] != expect_arr[i - 1]) {
// 현재와 다음 스위치를 뒤집음
now_arr_1[i - 1] = 1 - now_arr_1[i - 1];
now_arr_1[i] = 1 - now_arr_1[i];
ans1++; // 뒤집은 스위치 수 증가
if (i != n - 1) {
now_arr_1[i + 1] = 1 - now_arr_1[i + 1]; // 마지막 스위치가 아니면 다음 스위치도 뒤집음
}
}
// 두 번째 경우에서 현재 스위치가 예상 상태와 다르면
if (now_arr_2[i - 1] != expect_arr[i - 1]) {
// 현재와 다음 스위치를 뒤집음
now_arr_2[i - 1] = 1 - now_arr_2[i - 1];
now_arr_2[i] = 1 - now_arr_2[i];
ans2++; // 뒤집은 스위치 수 증가
if (i != n - 1) {
now_arr_2[i + 1] = 1 - now_arr_2[i + 1]; // 마지막 스위치가 아니면 다음 스위치도 뒤집음
}
}
}
// 마지막 스위치의 상태가 예상 상태와 다른지 확인
if (now_arr_1[n - 1] != expect_arr[n - 1]) ans1 = INF; // 첫 번째 경우 실패
if (now_arr_2[n - 1] != expect_arr[n - 1]) ans2 = INF; // 두 번째 경우 실패
// 최소한의 스위치 뒤집기 횟수를 출력하거나, 두 경우 모두 불가능할 때 -1을 출력
if (ans1 == INF && ans2 == INF)
System.out.println(-1);
else
System.out.println(Math.min(ans1, ans2));
}
}
'자료구조 > 문제풀이' 카테고리의 다른 글
[백준 JAVA] 21941 문자열 제거 (0) | 2024.10.01 |
---|---|
[백준 JAVA] 7579 앱 (0) | 2024.10.01 |
[백준 JAVA] 17836 공주님을 구해라! (0) | 2024.10.01 |
알고리즘 스터디 3주차 문제정리 (0) | 2024.09.30 |
[백준 JAVA] 14500 테트로미노 (0) | 2024.09.27 |