문제 설명: 문제 링크
성능 요약
메모리: 15832 KB, 시간: 120 ms
분류
구현, 시뮬레이션
제출 일자
2025년 7월 21일 11:22:47
해당 문제 로직은 크게 두 가지로 나뉜다.
첫번째는 남학생.
“스위치 번호가 자기가 받은 수의 배수이면, 그 스위치의 상태를 바꾼다. 즉, 스위치가 켜져 있으면 끄고, 꺼져 있으면 켠다. <그림 1>과 같은 상태에서 남학생이 3을 받았다면, 이 학생은 <그림 2>와 같이 3번, 6번 스위치의 상태를 바꾼다.”
→ 스위치 번호를 입력 받아 해당 스위치 번호를 따로 저장한 후, while문을 통해 스위치 번호에 해당하는 값을 조건문을 통해 바꾼 후 따로 저장한 스위치 번호 값을 + 해주는 방식으로 스위치 번호 수의 배수를 변경해나가면 된다.
두번째는 여학생.
”여학생은 자기가 받은 수와 같은 번호가 붙은 스위치를 중심으로 좌우가 대칭이면서 가장 많은 스위치를 포함하는 구간을 찾아서, 그 구간에 속한 스위치의 상태를 모두 바꾼다. 이때 구간에 속한 스위치 개수는 항상 홀수가 된다.”
→ 처음엔 count 라는 변수를 1로 지정해놓고, 스위치 번호 - count 와 스위치 번호 + count 를 비교해 같으면 count의 값에 + 1을 한 후 비교하는 것을 반복하도록 설정했으나, 런타임 에러(배열 인덱스 길이 초과)가 나옴.
→ 해당 값들을 비교할 수 있는 ‘범위’를 지정해두고, 그 범위 내에서 값들을 비교하도록 변경하면 런타임 에러에서 안전하게 비교할 수 있음!
그리고
“스위치의 상태를 1번 스위치에서 시작하여 마지막 스위치까지 한 줄에 20개씩 출력한다. 예를 들어 21번 스위치가 있다면 이 스위치의 상태는 둘째 줄 맨 앞에 출력한다. 켜진 스위치는 1, 꺼진 스위치는 0으로 표시하고, 스위치 상태 사이에 빈칸을 하나씩 둔다.”
→ 출력에 주의하자! count 변수를 지정해 if 조건문으로 처리함.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int n,k;
static int[] num;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb = new StringBuilder();
n = Integer.parseInt(br.readLine());
num = new int[n+1];
num[0] = Integer.MAX_VALUE;
st = new StringTokenizer(br.readLine());
for(int i = 1; i <= n; i++){
num[i] = Integer.parseInt(st.nextToken());
}
k = Integer.parseInt(br.readLine());
for(int i=0; i<k; i++){
st = new StringTokenizer(br.readLine());
int gender = Integer.parseInt(st.nextToken());
int switchNum = Integer.parseInt(st.nextToken());
if(gender == 1){ //남자
int count = switchNum;
while(switchNum <= n){
num[switchNum] = num[switchNum] == 0 ? 1 : 0; //스위치 상태가 0이면 1로, 1이면 0 으로
switchNum += count;
}
}
else{ //여자
int count = 1;
while(true){
if(switchNum - count < 1 || switchNum + count > n){
break;
}
if(num[switchNum - count] == num[switchNum + count]){
count++;
}
else{
count--;
break;
}
}
for(int j=switchNum-count; j<=switchNum + count; j++){
num[j] = num[j] == 0 ? 1 : 0;
}
}
}
int count = 0;
for(int i=1; i<=n; i++){
if(count >= 20){
count = 0;
sb.append("\n");
}
sb.append(num[i] + " ");
count++;
}
System.out.println(sb.toString());
}
}
여학생 로직의 경우에서 문제가 됐다.
int count = 1;
while(true){
if(switchNum - count < 1 || switchNum + count > n){
break;
}
if(num[switchNum - count] == num[switchNum + count]){
count++;
}
else{
count--;
break;
}
}
for(int j=switchNum-count; j<=switchNum + count; j++){
num[j] = num[j] == 0 ? 1 : 0;
}
예를 들어
2
1 1
3
1 1
2 1
2 2
와 같은 입력이 주어졌다고 해보자.
문제가 될 수 있는 부분인 2 2 이다.
이 경우,학생은 여자이며 switchNum이 2라는 값을 받게 된다.
그렇다면 while문 안에 들어감과 동시에
if(switchNum - count < 1 || switchNum + count > n){
break;
}
이 if문 조건에서 걸려 break 문으로 빠져나오게 되고, count는 그대로 1이 된다.
배열 인덱스의 범위는 2까지인데, switchNum은 2, count는 1인 상황이므로
for(int j=switchNum-count; j<=switchNum + count; j++){
num[j] = num[j] == 0 ? 1 : 0;
}
해당 로직에서 인덱스 범위를 벗어난 3까지 for문을 돌리게 된다.
즉 런타임 에러가 나오게 된다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int n,k; //스위치 개수 , 학생 수
static int[] num; //스위치 상태 표시 배열
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
n = Integer.parseInt(br.readLine());
num = new int[n+1];
num[0] = Integer.MAX_VALUE; //스위치 상태 0번은 사용 X
//스위치 상태 넣어주기.
StringTokenizer st = new StringTokenizer(br.readLine());
for(int i = 1; i <= n; i++){
num[i] = Integer.parseInt(st.nextToken());
}
//학생 수 입력 받기
k = Integer.parseInt(br.readLine());
for(int i=0; i<k; i++){
st = new StringTokenizer(br.readLine());
//각각 성별, 스위치 번호 입력 받기
int gender = Integer.parseInt(st.nextToken());
int switchNum = Integer.parseInt(st.nextToken());
if(gender == 1){ //남자
studentMan(switchNum);
}
else{ //여자
studentWoman(switchNum);
}
}
printSwitches();
}
public static void printSwitches(){
int count = 0;
for(int i=1; i<=n; i++){
if(count >= 20){
count = 0;
sb.append("\n");
}
sb.append(num[i] + " ");
count++;
}
System.out.println(sb.toString());
}
public static void studentWoman(int switchNum){
/*
최대 범위를 설정함.
예: 만약 switchNum이 3이고, n이 8이라면 최대로 비교할 수 있는 범위는 2임.
즉 3을 기준으로 1,5번 2,4번 인덱스를 비교하는 것이 최대라고 설정해두면 런타임 에러(배열 인덱스 값 넘어섬)를 벗어날 수 있음.
*/
int range = Math.min(switchNum - 1, n - switchNum);
int count = 0;
for(int j = 0; j<=range; j++){
if(num[switchNum-j] == num[switchNum+j]){
count = j;
}
else{
break;
}
}
for(int j = switchNum - count; j <= switchNum + count; j++){
num[j] = num[j] == 0 ? 1 : 0;
}
}
public static void studentMan(int switchNum){
int count = switchNum;
while(switchNum <= n){
num[switchNum] = num[switchNum] == 0 ? 1 : 0; //스위치 상태가 0이면 1로, 1이면 0 으로
switchNum += count;
}
}
}