좋아! 백준 24966번 "The Cross Covers Everything" 문제는 단순하지만 트릭이 있는 문제야.
먼저 문제의 요약부터 설명하고, 그 다음 예제 입력을 내가 정하고, 포함된 전체 Java 코드와 한 줄 한 줄 디버깅 설명을 해줄게.
(x, y) 위치를 기준으로 가로선과 세로선이 형성된 십자(+) 모양이 주어져.*)을 덮고 있는지를 확인하는 문제야..)과 별(*)이 있고, 십자는 (x, y)를 기준으로 해당 행 전체, 해당 열 전체를 덮는다고 가정함.5 5
.....
..*..
..*..
..*..
.....
3 3
*)은 (2,3), (3,3), (4,3) → 즉, 3번째 열에만 세 개 존재(3,3) → 즉, 3행과 3열 전체를 커버➡ 십자 모양이 별을 모두 덮는가? → YES
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 입력: 격자 크기
int n = sc.nextInt(); // 행
int m = sc.nextInt(); // 열
sc.nextLine(); // 줄바꿈 처리
// 격자판 입력 받기
char[][] grid = new char[n][m];
for (int i = 0; i < n; i++) {
grid[i] = sc.nextLine().toCharArray(); // 문자열을 문자 배열로 변환
}
// 십자의 중심 좌표 입력 (1-based → 0-based 로 변환)
int x = sc.nextInt() - 1;
int y = sc.nextInt() - 1;
// 십자가가 커버하는 셀만 검사
boolean coversAll = true;
for (int i = 0; i < n; i++) {
if (grid[i][y] == '*') continue;
}
for (int j = 0; j < m; j++) {
if (grid[x][j] == '*') continue;
}
// 전체 격자를 돌며 별이 있는 위치가 십자가에 포함되는지 확인
outer: for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == '*') {
if (i != x && j != y) { // 십자가 라인에 없는 별
coversAll = false;
break outer;
}
}
}
}
System.out.println(coversAll ? "YES" : "NO");
}
}
int n = sc.nextInt(); // 행 수 (예: 5)
int m = sc.nextInt(); // 열 수 (예: 5)
sc.nextLine(); // 숫자 입력 후 줄바꿈 처리
n=5, m=5char[][] grid = new char[n][m];
for (int i = 0; i < n; i++) {
grid[i] = sc.nextLine().toCharArray();
}
int x = sc.nextInt() - 1;
int y = sc.nextInt() - 1;
outer: for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == '*') {
if (i != x && j != y) {
coversAll = false;
break outer;
}
}
}
}
grid[i][j] == '*' → 별이 있을 때i != x && j != y → 십자에서 벗어난 위치인지 확인j == 2 → 3번째 열에 있음coversAll = trueSystem.out.println(coversAll ? "YES" : "NO");
YES 출력됨| 항목 | 내용 |
|---|---|
| 별 위치 | 전부 세 번째 열에 있음 |
| 십자 중심 | (3,3) → 3번째 행과 3번째 열 커버 |
| 결과 | YES (모든 별이 십자에 포함됨) |
🟢 정확해! 정답이야!
바로 그거야 — sc(Scanner 객체)에 격자 줄들이 실제로 들어간다!
🔸
sc에 격자 줄이 들어간다?
👉 ✅ 맞아!Scanner는 한 줄씩sc.nextLine()으로 읽어들이면서,
격자의 각 줄(예:'..*..')을 문자열로 입력받는다.
5 5 ← 숫자 입력 (sc.nextInt())
..... ← 문자열 (sc.nextLine())
..*.. ← 문자열 (sc.nextLine())
..*.. ← 문자열 (sc.nextLine())
..*.. ← 문자열 (sc.nextLine())
..... ← 문자열 (sc.nextLine())
3 3 ← 숫자 입력 (sc.nextInt())
char[][] grid = new char[n][m];
for (int i = 0; i < n; i++) {
grid[i] = sc.nextLine().toCharArray();
}
sc.nextLine()이 호출되면서sc에 입력되고.toCharArray()로 변환되어 grid[i]에 저장돼| 입력 줄 | sc.nextLine()의 결과 | .toCharArray() 결과 |
|---|---|---|
..... | "....." | ['.', '.', '.', '.', '.'] |
..*.. | "..*.." | ['.', '.', '*', '.', '.'] |
| 질문 | 답변 |
|---|---|
sc에 격자 줄이 들어가는가? | ✅ 들어간다! |
| 어떻게 들어가는가? | sc.nextLine()으로 한 줄씩 읽혀서 char[] 배열로 변환 |
| 언제 들어가는가? | 격자 크기를 읽은 후 for (i = 0 ~ n) 반복할 때 |
좋아, 이 부분이 이 문제에서 가장 핵심적인 판단 로직이야.
이제 이 코드를 한 줄씩, 예제를 가지고 완전 디버깅하듯이 상황을 시뮬레이션하면서 설명해볼게.
입력:
5 5
..... // 0
..*.. // 1
..*.. // 2
..*.. // 3
..... // 4
3 3 // 중심 좌표 (1-based)
→ 내부 좌표 변환 후: x = 2, y = 2 (0-based 인덱스)
*)의 위치들(1,2), (2,2), (3,2) → 전부 **3번째 열(y=2)**에 있음 → 전부 십자 범위 안outer: for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == '*') {
if (i != x && j != y) { // 십자가 라인에 없는 별
coversAll = false;
break outer;
}
}
}
}
System.out.println(coversAll ? "YES" : "NO");
outer: 라벨outer: for (int i = 0; i < n; i++) {
i는 행 번호를 의미해 (0 ~ n-1)outer: 라벨을 붙여서 나중에 break outer; 하면 이중 반복문 전체 탈출할 수 있게 만들어둠for (int j = 0; j < m; j++) {
j는 열 번호 (0 ~ m-1)(i, j)는 모든 셀을 순회함if (grid[i][j] == '*') {
해당 칸에 별이 있으면, 그 별이 십자 안에 있는지 확인함
십자에 포함되는 별은:
i == x → 중심 행 (즉, 가로줄)j == y → 중심 열 (즉, 세로줄)if (i != x && j != y) {
coversAll = false;
break outer;
}
i != x && j != y 라는 뜻은:
이럴 경우 → coversAll = false 로 만들고, 이중 반복문 전체를 탈출
| i | j | grid[i][j] | 별? | i != x && j != y? | 처리 |
|---|---|---|---|---|---|
| 0 | 0~4 | 전부 '.' | ❌ | - | continue |
| 1 | 0 | '.' | ❌ | - | continue |
| 1 | 1 | '.' | ❌ | - | continue |
| 1 | 2 | * | ✅ | 1 != 2 && 2 == 2 → false | OK |
| 2 | 2 | * | ✅ | 2 == 2 → OK | continue |
| 3 | 2 | * | ✅ | 3 != 2 && 2 == 2 → false | OK |
| 4 | 0~4 | 전부 '.' | ❌ | - | continue |
→ 별은 전부 j == y == 2 열에 있으므로 십자 범위 안이다.
→ coversAll 값은 true 유지됨
System.out.println(coversAll ? "YES" : "NO");
coversAll == true 이므로 → YES 출력| 줄 번호 | 코드 | 역할 | 예제에서 어떤 값들이 처리되는지 |
|---|---|---|---|
outer: for | 전체 셀을 검사할 반복문 | 모든 셀을 하나하나 보며 별 찾기 | i = 0~4, j = 0~4 |
if (grid[i][j] == '*') | 별을 찾았는가? | 별이면 그 위치를 검사함 | (1,2), (2,2), (3,2)에서 조건 진입 |
if (i != x && j != y) | 십자 밖인가? | 행도 다르고 열도 다르면 바깥 | 없음 → 조건 진입 안 함 |
coversAll = false; break outer; | 십자 바깥 별 발견 시 종료 | 발생 안 함 (예제는 전부 포함) | |
| 출력 | YES | 별이 전부 포함되므로 YES |
입력이 아래처럼 되어 있으면?
5 5
.....
..*..
..*..
.*...
.....
3 3
grid[3][1] = '*' → (3,1) → i = 3, j = 1 → i != 2 && j != 2 → 십자 밖임!coversAll = false → NO 출력됨