Algorithm

[백준] 전구와 스위치 2138번 (c++) 그리디

salmon16 2025. 2. 19. 22:19

출처 : https://www.acmicpc.net/problem/2138

 

풀이 방법

이 문제는 전구를 켜는 순서가 중요하지 않으며, 또한, 전구를 여러 번 켜고 끄더라도 같은 상태로 반복하므로, 각 전구는 0번 또는 1번만 변경하면 된다는 점을 파악하는 것이 중요하다. (2번 스위치 하는 것은 0번 스위치 하는 것과 동일)

 

문제 해결을 위해 첫 번째 전구부터 시작하여 전구를 바꾸는 경우와 그대로 두는 경우를 고려하며 탐색한다. 이 과정에서 현재 인덱스 이전의 전구가 원하는 정답 상태와 다르다면, 반드시 현재 전구를 바꿔야 한다는 규칙을 도출할 수 있다. 이러한 방식으로 인덱스를 늘려가며 조건을 적용해 나가면 최소 횟수로 전구를 원하는 상태로 만들 수 있다.

 

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int n, ans = 987654321;
string src, dst;
int arr[100001], goal[100001];


// 처음을 선택하냐 마냐를 고려하기

void turn_lamp(int idx) {
	arr[idx - 1] = (arr[idx - 1] + 1) % 2;
	arr[idx] = (arr[idx] + 1) % 2;
	if (idx + 1 < src.length()) arr[idx + 1] = (arr[idx + 1] + 1) % 2;
}

void init() {
	for (int i = 0; i < src.length(); i++) { // 램프 초기화
		if (src[i] == '0') arr[i] = 0;
		else arr[i] = 1;
	}
}

bool check() {
	for (int i = 0; i < src.length(); i++) {
		if (arr[i] != goal[i]) return false;
	}
	return true;
}
void sol() {
	// 1번을 선택했을 때, 2번이 다르다면 선택하면 안된다.

	// 이전 개 다르면 본인을 선택해야 한다. (무조건)
	// 이전 개 같다면 본인을 선택하면 안된다.(무조건)
	

	init();
	// 0번을 킨경우
	arr[0] = (arr[0] + 1) % 2;
	arr[1] = (arr[1] + 1) % 2;
	int cnt = 1;
	for (int i = 1; i < src.length(); i++) {
		if (arr[i - 1] != goal[i - 1]) {
			turn_lamp(i);
			cnt++;
		}
	}
	if (check()) ans = cnt;
	

	init();
	cnt = 0;
	// 0번을 안킨경우
	for (int i = 1; i < src.length(); i++) {
		if (arr[i - 1] != goal[i - 1]) {
			turn_lamp(i);
			cnt++;
		}
	}

	if (check()) ans = min(ans, cnt);
}

int main() {

	cin >> n;
	cin >> src >> dst;
	
	for (int i = 0; i < src.length(); i++) { // 램프 초기화
		if (dst[i] == '0') goal[i] = 0;
		else goal[i] = 1;
	}

	sol();

	if (ans == 987654321) cout << -1;
	else cout << ans << endl;
	return 0;
}