본문 바로가기
코딩 테스트/백준

1248 Guess (자바스크립트)

by 위그든씨 2025. 1. 12.

Given a sequence of integers, a1, a2, …, an, we define its sign matrix S such that, for 1 ≤ i ≤ j ≤ n, Sij="+" if ai + … + aj > 0; Sij="−" if ai + … + aj < 0; and Sij="0" otherwise. 

For example, if (a1, a2, a3, a4)=( −1, 5, −4, 2), then its sign matrix S is a 4×4 matrix: 

 12341234
- + 0 +
  + + +
    - -
      +

We say that the sequence (−1, 5, −4, 2) generates the sign matrix. A sign matrix is valid if it can be generated by a sequence of integers. 

Given a sequence of integers, it is easy to compute its sign matrix. This problem is about the opposite direction: Given a valid sign matrix, find a sequence of integers that generates the sign matrix. Note that two or more different sequences of integers can generate the same sign matrix. For example, the sequence (−2, 5, −3, 1) generates the same sign matrix as the sequence (−1,5, −4,2). 

Write a program that, given a valid sign matrix, can find a sequence of integers that generates the sign matrix. You may assume that every integer in a sequence is between −10 and 10, both inclusive. 

입력

The first line contains an integer n(1 ≤ n ≤ 10), where n is the length of a sequence of integers. The second line contains a string of n(n+1)/2 characters such that the first n characters correspond to the first row of the sign matrix, the next n−1 characters  to the second row, ..., and the last character to the n-th row. 

출력

Output exactly one line containing a sequence of n integers which generates the sign matrix. If more than one sequence generates the sign matrix, you may output any one of them. Every integer in the sequence must be between −10 and 10, both inclusive.

=====

문제 분석

정답으로 출력 될 배열은 n의 길이를 가졌다. 이를 arr로 칭한다.

입력에 주어진 문자열을 통해 gr을 구할 수 있으며 gr[i][j] 는 arr[i] 부터 arr[j]까지 합의 부호를 나타낸다.

const gr = Array.from({ length: n }, () =>
        Array.from({ length: n }, () => ' ')
    );
let c = 0;
for (let i = 0; i < n; i++) {
    for (let j = i; j < n; j++) {
	    gr[i][j] = str[c++];
    }
}

각 인덱스의 숫자는 -10부터 10의 값을 나타나고 있으며 

각 인덱스별로 -10부터 10의 값을 넣어보면서 재귀를 돌린다면 arr를 구할 수 있다. 

이때 첫 인덱스부터 숫자를 넣어보면서 gr의 적혀있는 부호를 통해 알맞은 숫자를 구할 수 있겠지만, 이럴 경우 첫 인덱스부터 끝 인덱스까지 조건에 부합하는지 찾아봐야하고, 그 다음으로는 두번째 인덱스부터 끝 인덱스까지 맞는지 또 구해봐야한다.

이러한 불필요한 연산을 줄이기 위해 마지막 인덱스부터 부합하는 요소들을 찾으며 그 이전 인덱스에 숫자를 넣어보며 찾아봐야한다.

const next = row - 1;
let a = gr[next][next] === '-' ? -1 : 1;

for (let t = 1; t <= 10; t++) {
    const num = t * a;
    let s = num;
    let isSuccess = true;

    for (let col = row; col < n; col++) {
        s += arr[col];

        if (s === 0 && gr[next][col] !== '0') {
            isSuccess = false;
            break;
        }
        if (s > 0 && gr[next][col] !== '+') {
            isSuccess = false;
            break;
        }
        if (s < 0 && gr[next][col] !== '-') {
            isSuccess = false;
            break;
        }
    }
    if (isSuccess) {
        const temp = [...arr];
        temp[next] = num;
        dfs(next, temp);
    }
}

이 로직대로 재귀를 돌린다면 정답이 출력됨.

오답 노트

이러한 로직으로 배열을 구하는데 계속 틀렸길래 문제를 읽어보니 첫번째 인덱스만 0이 아닌 수가 온다는 점을 놓쳐서였다.

정답 코드

const main = (n, str) => {
    const gr = Array.from({ length: n }, () =>
        Array.from({ length: n }, () => ' ')
    );
    let c = 0;
    for (let i = 0; i < n; i++) {
        for (let j = i; j < n; j++) {
            gr[i][j] = str[c++];
        }
    }

    const dfs = (row, arr) => {
        if (row === 0) {
            console.log(arr.join(' '));
            process.exit(0);
        }
        const next = row - 1;

        if (gr[next][next] === '0') {
            let s = 0;
            let isSuccess = true;

            for (let col = row; col < n; col++) {
                s += arr[col];

                if (s === 0 && gr[next][col] !== '0') {
                    isSuccess = false;
                    break;
                }
                if (s > 0 && gr[next][col] !== '+') {
                    isSuccess = false;
                    break;
                }
                if (s < 0 && gr[next][col] !== '-') {
                    isSuccess = false;
                    break;
                }
            }
            if (isSuccess) {
                const temp = [...arr];
                temp[next] = 0;
                dfs(next, temp);
            }

            return;
        }

        let a = gr[next][next] === '-' ? -1 : 1;

        for (let t = 1; t <= 10; t++) {
            const num = t * a;
            let s = num;
            let isSuccess = true;

            for (let col = row; col < n; col++) {
                s += arr[col];

                if (s === 0 && gr[next][col] !== '0') {
                    isSuccess = false;
                    break;
                }
                if (s > 0 && gr[next][col] !== '+') {
                    isSuccess = false;
                    break;
                }
                if (s < 0 && gr[next][col] !== '-') {
                    isSuccess = false;
                    break;
                }
            }
            if (isSuccess) {
                const temp = [...arr];
                temp[next] = num;
                dfs(next, temp);
            }
        }
    };

    if (str.at(-1) === '0') {
        const temp = Array.from({ length: n }, () => -1);
        temp[n - 1] = 0;

        dfs(n - 1, temp);
    } else {
        let aa = str.at(-1) === '-' ? -1 : 1;
        for (let i = 1; i <= 10; i++) {
            const temp = Array.from({ length: n }, () => -1);
            temp[n - 1] = i * aa;

            dfs(n - 1, temp);
        }
    }
};
const input = require('fs')
    .readFileSync(process.platform === 'linux' ? '/dev/stdin' : './input.txt')
    .toString()
    .trim()
    .split('\n');

const n = +input[0];
const gr = input[1].split('');

main(n, gr);

'코딩 테스트 > 백준' 카테고리의 다른 글

2580 스도쿠 (자바스크립트)  (0) 2025.01.13
16197 두 동전  (0) 2025.01.13
6064 카잉 달력  (0) 2025.01.09
17298 오큰수 , 17299 오등큰수 (자바스크립트)  (0) 2025.01.08
1339 단어 수학 (자바스크립트)  (0) 2025.01.08