[백준-자바] N_1244 스위치 켜고 끄기

0woy·2024년 11월 9일
0

코딩테스트

목록 보기
38/40

📜 문제

  • 남학생: 받은 숫자 배수 스위치 상태 변경
  • 여학생: 받은 숫자 기준, 대칭이 되는 모든 스위치 상태 변경
  • 스위치 상태는 20개 씩 출력 후 줄바꿈

그렇게 어려운 문제는 아닌데, 오래걸렸다..
처음에 문제를 제대로 안 읽어서 배수인 줄 몰랐고,, 20개 줄바꿈도 안 했고
무엇보다 인덱스를 잘 못 다뤘다.


생각하기

풀이 방법은 간단하다.
그냥 위 조건대로 구현을 하면 되는 문제긴 한데, 인덱스 조절하는 게 좀 번거로웠다.

배열의 경우 0부터 시작을 하는데, 문제에서는 스위치 번호가 1부터 시작을 해서
배열의 크기를 주어진 수+1 만큼 해주고 구현하면 된다.


🍳 전체 소스 코드

import java.io.*;
import java.util.StringTokenizer;

public class N_1244 { 
    static int[] switches;

    public static void printSwitches(){
        StringBuilder sb = new StringBuilder();
        for(int i=1;i<switches.length;i++){
            sb.append(switches[i]+" ");
            if(i%20==0){
                sb.append("\n");
            }
        }
        System.out.println(sb.toString());
    }
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        StringTokenizer st =new StringTokenizer(br.readLine());

        switches = new int[n+1];
        for(int i=1;i<=n;i++){
            switches[i] = Integer.parseInt(st.nextToken());
        }
        int student = Integer.parseInt(br.readLine());
        while(student -- > 0){
            st = new StringTokenizer(br.readLine());
            int sex = Integer.parseInt(st.nextToken());
            int pos = Integer.parseInt(st.nextToken());

            calc(sex, pos);
        }
        printSwitches();
    }
    public static void calc(int sex, int pos){
        if(sex == 1){
            for(int i=1;pos*i<switches.length;i++){
                switches[pos*i] =
                        (switches[pos*i]==0)?1:0;
            }
        }else{
            int start, end;
            start = end=pos;
            while(start >=2 && end<switches.length-1){
                start--;
                end++;
                if(switches[start]!=switches[end]){
                    start ++;
                    end--;
                    break;
                }
            }
            for(int i=start;i<=end;i++){
                switches[i] =
                        (switches[i]==0)?1:0;
            }
        }
    }

}
  • main : 입력 및 초기화
  • calc : 남&여 학생에 따른 스위치 변화
  • printSwitches: 스위치 상태 출력

✍ 부분 코드 설명

Main 함수 - 입력 & 변수 초기화

 	static int[] switches;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        StringTokenizer st =new StringTokenizer(br.readLine());

        switches = new int[n+1];
        for(int i=1;i<=n;i++){
            switches[i] = Integer.parseInt(st.nextToken());
        }
        int student = Integer.parseInt(br.readLine());
        while(student -- > 0){
            st = new StringTokenizer(br.readLine());
            int sex = Integer.parseInt(st.nextToken());
            int pos = Integer.parseInt(st.nextToken());

            calc(sex, pos);
        }
        printSwitches();
    }
    
    ...   
  • switches: 스위치 상태 저장 배열
  • n: 스위치 개수
  • student: 학생 수
  • sex: 학생 성별
  • pos: 스위치 변경 기준 위치

들어온 입력대로 스위치 상태를 저장해 주고, 학생 수 만큼 calc 함수를 호출해서 스위치 상태를 변경한다.


calc 함수

    public static void calc(int sex, int pos){
        if(sex == 1){
            for(int i=1;pos*i<switches.length;i++){
                switches[pos*i] =
                        (switches[pos*i]==0)?1:0;
            }
        }else{
            int start, end;
            start = end=pos;
            while(start >=2 && end<switches.length-1){
                start--;
                end++;
                if(switches[start]!=switches[end]){
                    start ++;
                    end--;
                    break;
                }
            }
            for(int i=start;i<=end;i++){
                switches[i] =
                        (switches[i]==0)?1:0;
            }
        }
    }

sex 매개변수에 남학생은 1로, 여학생은 2로 들어온다.

1. 남학생

남학생은 스위치 번호가 자신이 받은 수의 배수이면 상태를 바꾼다.
예를 들어 3이 들어온 경우, 우리는 3번,6번, 9번 .. 스위치를 바꾼다.
i 값을 증가해 가면서 배수를 찾으면 돼서 여학생보다 쉽다.

2. 여학생

여학생은 자신이 받은 수의 스위치 번호를 기준으로 양 옆이 대칭인 모든 스위치의 상태를 바꾼다.

예를 들어 스위치의 초기상태가 1 1 0 0 0 1 0 이고, 여학생이 4번을 받은 경우,
[3번, 5번] 스위치가 0으로 대칭이고, [2번, 6번] 스위치가 1로 대칭이다.
하지만, [1번, 7번] 스위치는 각각 10이므로 대칭이 아니다.

결국, 2번~6번까지의 스위치의 상태를 변화시키므로 1 0 1 1 1 0 0 이 된다.

startend 변수를 이용해서 pos기준 왼쪽과 오른쪽을 탐색한다.

걍 보여주면서 설명

여학생인 경우 위와 같은 순서로 스위치 상태가 변경 된다.

Q. start가 2이하면 종료라 했는데, 3)과정에서 에서 start가 1인데 왜 안 끝나고 실행 돼?

A. 어 왜냐면 3) 과정은 조건문에서 start가 2일 때 실행이 됐는데,
실행문에서 start--로 줄여준 거니까 while은 start가 1인줄 아직 몰랑
그 담에 검사할 때 1인거 앎

보통 배열 탐색 반복문의 종료 조건은 0이상, 마지막 수 미만으로 설정한다.
그래서 처음에 while의 조건을 1이상, 9 (switches.lengthh) 미만으로 설정했더니 틀렸음

왜냐하면, 만약에 모든 스위치가 좌우 대칭인 경우에 end = 9가 되고, start는 0으로 종료가 될 건데, 그렇게 하면 우리는 배열의 범위를 넘어서기 때문에.. 인덱스 초과 에러가 나요~

그래서 while문의 종료조건이 start가 2이상, end가 마지막에서 두 번째 번호 미만으로 설정했다.

어차피 실행문 내에서 증감을 하기에 모든 원소를 살펴볼 수 있음

대충 요런 식으로 흘러감


printSwitches 함수

  public static void printSwitches(){
        StringBuilder sb = new StringBuilder();
        for(int i=1;i<switches.length;i++){
            sb.append(switches[i]+" ");
            if(i%20==0){
                sb.append("\n");
            }
        }
        System.out.println(sb.toString());
    }
    

20개 마다 줄바꿈 하라고 했으니 20으로 나누어 떨어지면 줄바꿈 문자 삽입
그대로 배열 출력하면 됨


✨ 결과

내가 젤 싫어하는 인덱스 초과 ;;;
보다시피 실버 4인데 오래걸렸다. 왜 구현에 이렇게 오래 걸렸지 ???
왜냐면 처음부터 문제 제대로 안 읽고 쉬워 보인다고 빠져가지고 생각 덜 해서 그래

구현 문제 좀 풀어봐야겠다.

0개의 댓글