Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 파이썬
- C
- 프로그래머스
- 코딩테스트사이트추천
- 자료구조
- 자바
- 웹
- 코딩테스트
- 개발자취업
- 항해99
- 운영체제
- Java
- 코드트리
- 개발자루틴
- 알고리즘
- #코드트리 #코딩테스트 #코테공부 #백트래킹 #알고리즘 기초
- 99클럽
- 플로이드-워셜
- 1일1코테
- 갭체크
- 코딩테스트준비
- 자바스크립트
- 연결 리스트
- til
- 오블완
- 코테공부
- 인접 행렬
- 프로그래밍 언어
- 티스토리챌린지
- 데이터베이스
Archives
- Today
- Total
와드의 블로그
1248번: Guess 본문
문제
- 10부터 10까지의 정수로 이루어진 N개의 수열 A가 있습니다. 이 수열의 i번째 수부터 j번째 수까지의 합의 부호(+, -, 0)가 주어질 때, 부호 조건들을 모두 만족하는 수열 A를 찾는 프로그램을 작성하는 문제입니다.
- 입력: 첫째 줄에 수열의 크기 N (1 ≤ N ≤ 10)이 주어집니다. 둘째 줄에는 N(N+1)/2 길이의 문자열 형태의 부호 배열이 주어집니다.
- 출력: 부호 조건을 만족하는 수열 A를 공백으로 구분하여 출력합니다. (조건을 만족하는 수열이 여러 개일 경우 아무거나 하나만 출력합니다.)
풀이: 백트래킹을 활용한 부분 합 유효성 검사
이 문제는 10개의 자리에 -10부터 10까지 21개의 숫자를 무작위로 채우면 21^10 번의 탐색이 필요하여 시간 초과가 발생합니다. 따라서 백트래킹(DFS)을 이용해 조건을 만족하지 않는 경우는 빠르게 가지치기(Pruning)를 해야 합니다.
- 2차원 배열 할당: 주어진 1차원 부호 문자열을 직관적으로 다루기 위해 넉넉하게 n x n 크기의 2차원 배열 a에 저장합니다. a[i][j]는 ans[i]부터 ans[j]까지의 합의 부호를 의미하게 됩니다.
- 1차 가지치기 (자신의 부호 활용):a[idx][idx]는 ans[idx] 숫자 하나만의 부호를 의미합니다. 따라서 무작정 -10부터 10까지 모두 탐색하지 않고, 부호가 '+'면 1~10, '-'면 -10~-1, '0'이면 0만 탐색하도록 반복문의 범위를 좁힙니다.
- 2차 가지치기 (부분 합 실시간 검사):idx 위치의 숫자를 임시로 채웠다면, 다음 숫자를 찾으러 재귀 호출(go(idx + 1))을 넘어가기 전에 check 함수로 유효성을 검사합니다. i를 idx부터 0까지 거꾸로 내려가면서 sum에 ans[i]를 누적해 더하면, 이는 곧 ans[i] + ... + ans[idx]의 합이 됩니다. 이때의 합의 부호가 a[i][idx]의 부호와 하나라도 다르다면 즉시 false를 반환하여 잘못된 경로를 쳐냅니다.
- 프로그램 조기 종료: 정답 수열을 하나라도 찾았다면 더 이상 탐색할 필요가 없으므로 System.exit(0)을 호출하여 프로그램을 완전히 종료합니다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n;
static char[][] a;
static int[] ans;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
n = Integer.parseInt(br.readLine());
// 인덱스 초과 오류 방지 및 편의를 위해 N x N 배열로 선언
a = new char[n][n];
String s = br.readLine();
int idx = 0;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
a[i][j] = s.charAt(idx++);
}
}
ans = new int[n];
go(0);
}
static void go(int idx) {
// N개의 숫자를 모두 채웠다면 정답을 출력하고 즉시 종료 (Base Case)
if (idx == n) {
for (int i = 0; i < n; i++) {
System.out.print(ans[i] + " ");
}
System.out.println();
System.exit(0);
}
char c = a[idx][idx];
// a[idx][idx] 부호에 따라 탐색 범위를 한정 (가지치기 1)
if (c == '0') {
ans[idx] = 0;
if (check(idx)) {
go(idx + 1);
}
} else if (c == '+') {
for (int i = 1; i <= 10; i++) {
ans[idx] = i;
if (check(idx)) {
go(idx + 1);
}
}
} else {
for (int i = -10; i <= -1; i++) {
ans[idx] = i;
if (check(idx)) {
go(idx + 1);
}
}
}
}
// 방금 채운 ans[idx]가 포함된 부분합들이 부호 조건과 일치하는지 검증 (가지치기 2)
static boolean check(int idx) {
int sum = 0;
// idx부터 0까지 거꾸로 더하면서 부분합을 확인
for (int i = idx; i >= 0; i--) {
sum += ans[i];
if (a[i][idx] == '+' && sum <= 0) {
return false;
}
if (a[i][idx] == '-' && sum >= 0) {
return false;
}
if (a[i][idx] == '0' && sum != 0) {
return false;
}
}
return true;
}
}
알고리즘 분류
브루트포스 알고리즘 (Brute Force), 백트래킹 (Backtracking)
'PS > B.O.J' 카테고리의 다른 글
| 10971번: 외판원 순회 2 (0) | 2026.04.30 |
|---|---|
| 10972번: 다음 순열 (0) | 2026.04.30 |
| 15661번: 링크와 스타트 (0) | 2026.04.29 |
| 14501번: 퇴사 (0) | 2026.04.29 |
| 1759번: 암호 만들기 (0) | 2026.04.29 |