https://www.acmicpc.net/problem/1244
1. 서론
내가 문제를 대충 읽는 거겠지만... 진짜 생각지도 못한 조건에 걸려서 깜짝 놀랐다. 바로...
출력 형식이 잘못되었습니다.
이 에러는 아마도... 처음이거나 두 번째 정도일 것이다. 일단 기억에 없는데 어쨌든 구글에 뒤져보니 출력되는 값 자체는 답이 맞으나 출력 형식이 잘못됐다는 것이다. 그래서 문자열 출력할 때 설마 배열 마지막 자리에 공백 문자 있다고 이라는 거임? 하고 고쳐봤는데 여전히 꼼짝을 안 해서 질문검색을 때렸더니 이 문제의 조건이 바로... 20개씩 잘라서 출력하는 것이었다.... '충격'
2. 문제 풀이
n개의 스위치가 주어진다. 스위치는 0과 1의 값을 갖고 있는 배열이다. 학생의 성별과 스위치의 번호가 주어지는데 이 번호를 기준으로 성별별로 처리하는 방법이 다르다.
남학생인 경우) 입력된 스위치 번호의 배수인 스위치만 값을 변경한다. (0이면 1, 1이면 0으로)
여학생의 경우) 입력된 스위치 번호로부터 양쪽 대칭의 값을 확인하고 그 값들이 대칭일 경우 그 범위만큼 값을 변경한다. 범위 확장은 양쪽이 대칭하지 않을 때까지 계속된다.
입력으로 주어진 경우를 다 처리했을 때 스위치의 상태를 구하는 문제이다.
+
스위치는 20개씩 출력하며 그 이상인 경우는 다음 줄에서 출력한다.
남학생의 경우에는 그냥 간단하게 입력받은 번호의 배수, 즉 그 번호로 나누었을 때 나머지 값이 0인 것들만 값을 바꿔줬다.
여학생의 경우에는 변수를 써서 입력받은 값을 기준으로 양쪽 방향으로 더하고 빼면서 그 두 개의 값들이 대칭하는지를 체크해줬다. 대칭하지 않을 때까지 변수를 ++ 하고 (입력받은 값 - 변수) ~ (입력받은 값 + 변수) 범위 사이를 돌면서 값을 바꿔줬다. 그리고 대칭하지 않는 경우에는 입력된 스위치 번호만 값을 바꿔준다.
3. 코드 설명
import java.awt.Point;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
int n = s.nextInt();
int[] a = new int[n]; //스위치
for (int i = 0; i < n; i++)
a[i] = s.nextInt();
n = s.nextInt();
ArrayList<Point> list = new ArrayList<>(); //학생들 정보
for (int i = 0; i < n; i++) {
int x = s.nextInt(); //성별
int y = s.nextInt(); //스위치 번호
Point p = new Point(x, y);
list.add(p);
}
for (int i = 0; i < n; i++) {
if (list.get(i).x == 1) {
for (int j = 0; j < a.length; j++)
if (list.get(i).y <= (j + 1) && (j + 1) % list.get(i).y == 0)
a[j] = (a[j] == 0) ? 1 : 0;
}
else {
int j = 1;
while(true) { //스위치 값을 기준으로 양쪽으로 대칭인가 확인
if (list.get(i).y - j - 1 < 0 || list.get(i).y + j - 1 > a.length - 1) break;
if (a[list.get(i).y - j - 1] != a[list.get(i).y + j - 1]) break;
j++;
}
j--;
if (j >= 1) //양쪽 범위만큼 값 변경
for (int k = list.get(i).y - j - 1; k <= list.get(i).y + j - 1; k++)
a[k] = (a[k] == 0) ? 1 : 0;
else
a[list.get(i).y - 1] = (a[list.get(i).y - 1] == 0) ? 1 : 0;
}
}
for (int i = 0; i < a.length; i++) {
sb.append(a[i] + " ");
if ((i + 1) % 20 == 0)
sb.append("\n");
}
System.out.println(sb);
}
}
StringBuilder를 쓰면 효율이 좋다길래 써봤는데 개미 눈물만큼 빨라졌다. 그래도 문장이 더 길어지면 더 효과가 크겠지....?(아마도)
Point를 사용해서 학생의 성별과 스위치 번호를 세트로 묶었다. 난 아직도 자바에 적응 중인데 list.get(i) 이게 너무 어색하다. 너무 쓸 때 없이 코드 길어지는 느낌...
while문을 돌면서 대칭 확장 범위를 카운트 했는데 배열이다 보니 대칭 이외에도 범위의 양쪽 바깥으로 나가지 않도록 처리해줬다.
그리고 자바로 쓰니까 코드 길어지는게 너무 신경 쓰여서 오랜만에 삼항 연산자도 써봤다...
'Algorithm' 카테고리의 다른 글
[JAVA] 백준 2578 빙고 (0) | 2022.08.04 |
---|---|
[JAVA] SWEA 1289 원재의 메모리 복구하기 (0) | 2022.08.02 |
[JAVA] SWEA 1974 스도쿠 검증 (2) | 2022.07.11 |
[JAVA] SWEA 1961 숫자 배열 회전 (0) | 2022.07.09 |
[JAVA] SWEA 2001 파리 퇴치 (0) | 2022.07.09 |