목차
문제
링크
https://www.acmicpc.net/problem/11054
문제
수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.
예를 들어, {10, 20, 30, 25, 20}과 {10, 20, 30, 40}, {50, 40, 25, 10} 은 바이토닉 수열이지만, {1, 2, 3, 2, 1, 2, 3, 2, 1}과 {10, 20, 30, 40, 20, 30} 은 바이토닉 수열이 아니다.
수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)
출력
첫째 줄에 수열 A의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다.
주저리
더 간단하게 풀수있었던거같은데 일단 잘모르겠어서 해결을 해보는 위주로 하였다.
바이토닉 부분 수열은 증가만 하거나 감소만해도 가능하고 증가하다가 감소하는게 바이토닉 핵심이다.
testF함수는 증가하는함수이고 arrs에 길이 저장
testF2함수는 배열을 reverse()해서 똑같이 증가하는함수(=감소하는함수)를 구해준다.
arrsLow에 길이 저장
testF2는 배열을 뒤집은상태에서 증가하는것을 얻은거기때문에 한번더 reverse를 진행해주고
각 인덱스에맞춰서 더해준다.
-1을해주는이유는 자기자신이 포함이되기때문에 겹치는수를 한번 제거해주는 것이다.
그 합을 구해주고 max값을 보내주면 원하는 제출이 된다.
풀이
입력 데이터 처리
- 파일 시스템 모듈(fs)을 사용해 입력을 받습니다. 주석 처리된 부분은 실제 실행 환경에서 사용되며, 테스트를 위해 input 변수에 직접 데이터를 할당합니다.
- 입력 데이터는 줄 바꿈(\n)으로 구분되며, 숫자 배열은 공백으로 분리됩니다.
동적 프로그래밍 배열 초기화
- arrs 배열은 각 인덱스에서 끝나는 가장 긴 증가하는 부분 수열의 길이를 저장합니다.
- arrsLow 배열은 각 인덱스에서 시작하는 가장 긴 감소하는 부분 수열의 길이를 저장합니다.
부분 수열 계산 함수 testF
- 이 함수는 주어진 배열에 대해 각 요소를 순회하면서, 그 요소보다 앞에 있는 모든 요소들 중에서 해당 요소보다 작은 요소들의 arrs 값을 참조하여 가장 긴 증가하는 부분 수열의 길이를 업데이트합니다.
역방향 부분 수열 계산 함수 testF2
- 이 함수는 배열을 역순으로 처리하여, 각 요소에 대해 그 요소 이후에 있는 모든 요소들 중 해당 요소보다 큰 요소들의 arrsLow 값을 참조하여 가장 긴 감소하는 부분 수열의 길이를 계산합니다.
최종 계산
- testF와 testF2 함수로 계산된 두 배열 arrs와 arrsLow를 이용해 각 요소에서의 바이토닉 수열 길이를 계산합니다. 이는 두 값의 합에서 1을 빼줌으로써 각 요소가 중복 계산되는 것을 방지합니다.
- 결과 배열 중 최대값을 찾아 출력함으로써 가장 긴 바이토닉 부분 수열의 길이를 도출합니다.
코드
// 가장 긴 증가하는 부분 수열
var fs = require('fs');
var input = fs.readFileSync('/dev/stdin').toString();
let real = input.trim().split("\n");
let arrs = [];
let arrsLow = [];
function testF(N, rest) {
// for (let i = 0; i < 1; i++) arrs[0][i] = 1;
for (let i = 0; i < N; i++) {
// let reArr = [];
if (i === 0) {
arrs[i] = 1
}
else {
arrs[i] = 1;
let sliced = rest.slice(0, i);
let filtered = [];
for (let j = 0; j < sliced.length; j++) {
let r = sliced[j];
// console.log(rest[i], r, rest.slice(0, i));
if (rest[i] > r) {
filtered.push(arrs[j]);
}
}
if (filtered.length > 0) {
arrs[i] = Math.max(...filtered) + 1
}
}
// arrs.push(reArr);
}
}
function testF2(N, rest) {
// for (let i = 0; i < 1; i++) arrs[0][i] = 1;
let newRest = rest.reverse();
for (let i = 0; i < N; i++) {
// let reArr = [];
if (i === 0) {
arrsLow[i] = 1
}
else {
arrsLow[i] = 1;
let sliced = newRest.slice(0, i);
// console.log({ i, sliced, newRest });
let filtered = [];
for (let j = 0; j < sliced.length; j++) {
let r = sliced[j];
// console.log(rest[i], r, arrsLow);
if (rest[i] > r) {
filtered.push(arrsLow[j]);
}
}
// console.log({ filtered })
if (filtered.length > 0) {
arrsLow[i] = Math.max(...filtered) + 1
}
}
// arrs.push(reArr);
}
}
function solution(real) {
let [T, sec] = real;
let rest = sec.split(" ").map(Number);
if (Number(T) === 1) {
console.log(sec[0]);
return;
}
testF(Number(T), rest)
testF2(Number(T), rest)
let reArrL = arrsLow.reverse();
const result = arrs.map((value, index) => value + reArrL[index] - 1);
// console.log(arrs)
// console.log(arrsLow)
// console.log(result);
console.log(Math.max(...result))
}
solution(real);
'백준 > 골드' 카테고리의 다른 글
[node.js,백준]2580 - 스도쿠 (0) | 2024.05.21 |
---|---|
[node.js,백준]1987 - 알파벳 (0) | 2024.05.16 |
[node.js,백준]13398 - 연속합 2 (0) | 2024.05.11 |
[node.js,백준]2133 - 타일 채우기 (0) | 2024.05.10 |
[Node.js,백준]1377 - 버블 소트 (0) | 2024.05.08 |