문제 링크 : https://www.acmicpc.net/problem/2138

 

2138번: 전구와 스위치

N개의 스위치와 N개의 전구가 있다. 각각의 전구는 켜져 있는(1) 상태와 꺼져 있는 (0) 상태 중 하나의 상태를 가진다. i(1<i<n)번 스위치를="" 누르면="" i-1,="" i,="" i+1의="" 세="" 개의="" 전구의="" 상태가="" 바뀐다.="" 즉,="" 꺼져="" 있는="" 전구는="" 켜지고,="" 켜져="" 꺼지게="" 된다.="" 1번="" 눌렀을="" 경우에는="" 1,="" 2번="" 바뀌고,="" n번="" n-1,="" n개의="" 전구들의="" 현재="" 상태와="" 우리가="" 만들고자="" 하<="" p=""> </i<n)번>

www.acmicpc.net

 

 

 문제설명 

 

1. 첫번째 줄부터 전구의 갯수, 현재 전구의 상태, 원하는 전구의 상태가 주어짐

2. 전구와 스위치는 각각 N개씩있고 만약 i번째 스위치를 누른다면 i-1,i,i+1 번째 전구의 상태가 바뀐다.

3. 현재 전구의 상태에서 원하는 전구의 상태로 바꾸기위한 스위치 동작의 최소 횟수 출력.

 

 

 알고리즘 

 

1. 너무나 당연히 , 스위치를 누르거나 안누르거나 의 두가지 경우로 재귀를 돌리면 시간 초과가 발생한다 ^^ ..

2. 그래서 스위치를 가능한 그리디 하게 눌러줘야됨 .

3. i번째 전구의 상태에 마지막으로 영향을 미치는 스위치는 i+1번째 스위치이다. 이것을 이용하여 만약 i-1 번째  전구가

  목표로하는 전구의 상태가 아니면 누르는 식으로 재귀 함수를 진행 시킨다.

 

4. 주의할점은 첫번째 전구는 누르는 경우와 누르지않는 경우 두가지경우로 진행 시킨다.

 

 코드 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <iostream>
#include <string>
#include <algorithm>
 
using namespace std;
 
 
 
const int INF = 987654321
 
int N, answer;
 
string s, copyS, result; 
 
//스위치 누르는 함수
void push(int idx)
{
        if (idx > 0)
                 copyS[idx - 1= (copyS[idx - 1== '0') ? '1' : '0';
        
        copyS[idx] = (copyS[idx] == '0') ? '1' : '0';
 
        if (idx < N - 1)
                 copyS[idx + 1= (copyS[idx + 1== '0') ? '1' : '0';
}
 
 
 
void simulation(int idx, int cnt)
{
 
        if (idx == N - 1)
 
        {
 
                 //같은지 확인
 
                 bool flag = true;
 
                 for(int i=0; i<copyS.length(); i++)
 
                         if (copyS[i] != result[i])
 
                         {
 
                                 flag = false;
 
                                 break;
 
                         }
 
                 if (flag)
 
                         answer = min(answer, cnt);
 
                 //스위치를 눌러보고 다시 확인
 
                 push(idx);
 
                 flag = true;
 
                 for (int i = 0; i<copyS.length(); i++)
 
                         if (copyS[i] != result[i])
 
                         {
 
                                 flag = false;
 
                                 break;
 
                         }
 
                 if (flag)
 
                         answer = min(answer, cnt + 1);
 
                 return;
 
        }
 
       
 
        //스위치를 안 누른 상태
 
        if (copyS[idx - 1== result[idx - 1])
 
                 simulation(idx + 1, cnt);
 
        //스위치를 누르고
 
        push(idx);
 
        if (copyS[idx - 1== result[idx - 1])
 
                 simulation(idx + 1, cnt + 1);
 
        //원상복귀
 
        push(idx);
 
}
 
 
 
int main(void)
 
{
 
        ios_base::sync_with_stdio(0);
 
        cin.tie(0);
 
        cin >> N >> s >> result;
 
       
 
        answer = INF;
 
        //0번째 스위치를 누르지 않은 상태에서 시작
 
        copyS = s;
 
        simulation(10);
 
       
 
        //0번째 스위치를 누른 상태에서 시작
 
        copyS = s;
 
        push(0);
 
        simulation(11);
 
        if (answer == INF)
 
                 cout << -1 << "\n";
 
        else
 
                 cout << answer << "\n";
 
        return 0;
 
}
cs

'c++ > 백준' 카테고리의 다른 글

백준 1939번 : 중량 제한  (0) 2020.05.07
백준 2211번: 네트워크 복구  (0) 2020.05.07
백준 1238번 : 파티  (0) 2020.04.30
백준 1504번 : 특정한 최단 경로  (0) 2020.04.30
백준 1753번: 최단 경로  (0) 2020.04.30
ariz1623