[백준] 1244번 스위치 켜고 끄기-C++

potatoj11n·2024년 2월 16일

백준

목록 보기
29/36

1244번 스위치 켜고 끄기

문제 요약:

입력으로 받은 처음 스위치 상태에서 학생의 성별, 받은 수에 따라 스위치의 상태를 바꿨을 때 스위치의 마지막 상태를 출력

  • 스위치가 켜져있을 때 → 1, 꺼져있을 때 → 0
  • 학생이 남학생일 때 → 1:
    스위치 번호가 자기가 받은 수의 배수면 스위치의 상태를 바꾼다.
  • 학생이 여학생일 때 → 2:
    자기가 받은 수와 같은 번호의 스위치를 중심으로 좌우 대칭인 최대 구간의 스위치들의 상태를 전환한다. 구간에 속한 스위치의 개수는 홀수

예제 입력 1

8
0 1 0 1 0 0 0 1
2
1 3
2 3

예제 출력 1

1 0 0 0 1 1 0 1

초기 스위치 상태 : 0 1 0 1 0 0 0 1

  1. 1 3( 남학생 3번)→ 3, 6 번 스위치의 상태를 바꾼다.→ 0 1 1 1 0 1 0 1
  2. 2 3( 여학생 3번) → 3을 기준으로 좌우 대칭 →1~5번 스위치가 대칭 → 1 0 0 0 1 1 0 1

🤔 생각할 점:

Q. 남학생일 경우?

스위치의 상태를 1부터 N까지의 벡터로 생성해서 반복문으로 남학생의 번호의 배수들은 스위치를 전환

Q. 여학생일 경우?

스위치의 상태가 입력된 벡터에서 입력받은 인덱스를 기준으로 앞 뒤 양쪽으로 검사

투 포인터 (start,end로 둘 다 시작은 입력받은 인덱스로 한다.)

  • 투포인터 배열 안의 인덱스 수가 홀수인지 체크
  • start는 감소, end는 증가하면서 같은지 비교 , 같으면 boolean을 true로 해서 나중에 true인것만 전환

풀이 방법:

  1. 스위치의 개수 N, 스위치의 초기 상태(boolean 배열로), 학생 수(M), 학생의 성별과 학생이 받은 수(student, num) 순서로 입력 받는다.
  2. 스위치 개수만큼 초기 상태 입력받고 학생 수만큼 학생성별, 스위치 번호 입력
  3. 학생 성별이 남 학생이면 반복문으로 남학생의 스위치 번호의 배수들만 boolean 바꿔줌
  4. 여 학생이면 start, end 포인터를 num으로 초기화해서 start는 감소 end는 증가시키면서 비교
  5. 두 포인터가 같은 인덱스로 초기화 된 상태니까 포인터의 위치부터 바꾸고 반복문 실행, 대칭이 아니면 반복을 중단하도록 반복문을 만들어서 검사
  6. 대칭인 구간의 start end 인덱스를 찾아서 스위치를 전환

중요한 점:

대칭을 확인하기 전에 인덱스 위치를 바꿨기 때문에 대칭인 구간의 스위치를 전환할 때의 범위는 start는 한 인덱스 줄이기 전, end는 한 인덱스 늘어나기 전으로 설정해야한다.

내가 작성한 코드

#include<iostream>
using namespace std;

bool Switch[101];

int main(){
    int N,M,student,num;
    cin >> N;
    
    for(int i =1; i <=N;i++){
        cin >> Switch[i];
    }
    cin >> M;
    
    while(M--){
        cin >> student >> num;
        //남학생
        if(student == 1){
            for(int j=num;j <= N; j += num){//입력받은 스위치 번호의 배수들
                Switch[j] = !Switch[j];
            }
        }
        //여학생
        else{
            int start = num;
            int end = num;
            while(start >= 1 && end <= N){
                start--;
                end++;
                if(Switch[start] != Switch[end])//대칭이 아니면 반복 중단
                    break;     
             }
            for(int i = start + 1; i <= end-1;i++){
                Switch[i] = !Switch[i];
            }
        }
    }
   for (int i = 1; i <= N; i++)
	{
		cout << Switch[i] << ' ';
		if (i % 20 == 0)
			cout << '\n';
	}

    return 0;
}

🌟 초기화

int N,M,student,num;
    cin >> N;//스위치 개수
    
    for(int i =1; i <=N;i++){
        cin >> Switch[i];//스위치 초기 상태 배열
    }
    cin >> M;//학생 수

🌟 학생이 남학생일 경우

while(M--){
        cin >> student >> num;
        //남학생
        if(student == 1){
            for(int j=num;j <= N; j += num){//입력받은 스위치 번호의 배수들
                Switch[j] = !Switch[j];
            }
        }

학생 수만큼 반복하는 반복문 내에서 학생의 성별과 스위치 번호를 입력받는다.

학생이 1 ( 남학생)이면 반복문을 이용해 입력 받은 스위치 번호의 배수들만 boolean값을 바꿔서 스위치를 전환한다.

🌟 여학생인 경우

else{
      int start = num;//포인터 초기화
      int end = num;
      while(start >= 1 && end <= N){
          start--;
          end++;
          if(Switch[start] != Switch[end])//대칭이 아니면 반복 중단
              break;     
       }
      for(int i = start + 1; i <= end-1;i++){
          Switch[i] = !Switch[i];
      }
    }

포인터 두개를 입력받은 스위치 번호로 초기화하고 범위 내에서 start는 앞으로 end는 뒤로 이동시키면서 대칭인지 검사한다. 두 포인터가 같은 인덱스로 초기화되었기 때문에 인덱스 부터 움직이고 검사, 대칭이 아니면 바로 반복문 중단

대칭을 확인하는 반복문에서 포인터의 위치를 먼저 이동시키고 확인했기 때문에 마지막 실행에서는 포인터들이 대칭이 아닌 인덱스를 가리킨다. → 인덱스를 이동시킨 범위에 대해서 스위치를 전환해줘야한다.

🌟 출력

for (int i = 1; i <= N; i++)
	{
		cout << Switch[i] << ' ';
		if (i % 20 == 0)
			cout << '\n';
	}

스위치는 20개씩 출력하고 그 이상은 다음 줄에 출력해야한다.

→ 조건문으로 인덱스가 20을 넘으면 개행문자(엔터) 출력

0개의 댓글