From 08aff7b4c645240620ea6148c875012da1e67389 Mon Sep 17 00:00:00 2001 From: luckylooky2 Date: Mon, 30 Sep 2024 11:05:52 +0900 Subject: [PATCH] =?UTF-8?q?09.30:=20dp(=EC=97=B0=EC=86=8D=ED=95=A9=202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- baekjoon/13398.js | 32 +++++++++++++++++ baekjoon/2268.js | 91 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 baekjoon/13398.js create mode 100644 baekjoon/2268.js diff --git a/baekjoon/13398.js b/baekjoon/13398.js new file mode 100644 index 0000000..ed26c04 --- /dev/null +++ b/baekjoon/13398.js @@ -0,0 +1,32 @@ +// 연속합 2 : 동적 계획법 +const input = require("fs") + .readFileSync(0, "utf-8") + .trim() + .split("\n") + .map((v) => v.split(" ").map((v) => +v)); +const [n] = input.shift(); +const arr = input.shift(); +const dp = new Array(2).fill(null).map(() => new Array(n).fill(0)); +let answer = -Infinity; + +for (let i = 0; i < arr.length; i++) { + const curr = arr[i]; + // no skip: 이전까지 더한 수보다 현재가 더 크다면, 현재로 초기화 + dp[0][i] = Math.max(curr, (i > 0 ? dp[0][i - 1] : 0) + curr); + // skip + // - dp[0][i - 1]: 건너뛰지 않았을 때의 이전 항(현재를 건너뛴 경우) + // - dp[1][i - 1] + curr: 건너뛰었을 때의 이전 항(이전에서 건너뛴 경우 중 가장 최대값) + 현재 숫자 + dp[1][i] = i > 0 ? Math.max(dp[0][i - 1], dp[1][i - 1] + curr) : -Infinity; + answer = Math.max(answer, dp[0][i], dp[1][i]); +} + +console.log(answer); + +// Try 1 +// - no skip: 연속된 부호의 수를 하나로 더하고, 현재 음수일 때 다음 수가 더 크다면 음수를 포함하는 방법으로 계샨 +// - skip: 특정 수를 제외해야 하기 때문에, 음수는 하나로 더하지 않고 배열로 묶음. 뒤에 나오는 양수보다 합이 큰 음수 묶음을 하나씩 순회하면서 합계를 구함 + +// Try 2 : 동적 계획법 +// - 생각한 이유? 이전에 계산했던 값을 재사용할 수 있다고 생각 +// - 0행: 건너뛰지 않았을 때, 현재 순서에서 최대값 +// - 1행: 하나를 건너뛴 경우(현재 숫자 or 이전 숫자)를 포함하여, 현재 순서에서 최대값 diff --git a/baekjoon/2268.js b/baekjoon/2268.js new file mode 100644 index 0000000..f3a5e45 --- /dev/null +++ b/baekjoon/2268.js @@ -0,0 +1,91 @@ +// 수들의 합 7 : 세그먼트 트리 +const input = require("fs") + .readFileSync(0, "utf-8") + .trim() + .split("\n") + .map((v) => v.split(" ").map((v) => +v)); +const [n, m] = input.shift(); +const modified = new Map(); +const commands = input; +const [SUM, MODIFY] = [0, 1]; +const answer = []; + +const tree = [null]; +const element = Array.from({ length: 10 }).fill(0); + +function segmentTree(start, end, node = 1) { + if (start === end) return (tree[node] = start); + const mid = Math.floor((start + end) / 2); + const leftIndex = segmentTree(start, mid, 2 * node); + const rightIndex = segmentTree(mid + 1, end, 2 * node + 1); + // 구간에서 적용할 논리 : 합, 최대값, 최소값 ... + return (tree[node] = element[leftIndex] < element[rightIndex] ? leftIndex : rightIndex); +} + +segmentTree(0, element.length - 1); + +// function lowerBound(start, end, target, arr) { +// const mid = Math.floor((start + end) / 2); + +// if (start === end) { +// return start; +// } + +// if (arr[mid][0] >= target) { +// return lowerBound(start, mid, target, arr); +// } else { +// return lowerBound(mid + 1, end, target, arr); +// } +// } + +// for (const [command, arg1, arg2] of commands) { +// if (command === SUM) { +// const small = Math.min(arg1, arg2); +// const big = Math.max(arg1, arg2); +// const entries = [...modified.entries()].sort((a, b) => a[0] - b[0]); +// let result = 0; +// // small보다 같거나 큰 +// if (entries.length) { +// const index = lowerBound(0, entries.length - 1, small, entries); +// for (let i = index; i < entries.length; i++) { +// const [key, value] = entries[i]; +// if (key > big) { +// break; +// } +// result += value; +// } +// } +// answer.push(result); +// } else if (command === MODIFY) { +// modified.set(arg1, arg2); +// } +// } + +// console.log(answer.join("\n")); + +// sums[1] = 1 ~ 1 +// sums[3] = 1 ~ 3 +// sums[6] = 1 ~ 5 + +// Sum(4, 5) = sums[5] - sums[3] +// Modify(4, 1) + +// sums 배열 순회하며 최신화 => 시간을 줄여야 함 +// - 1) 1/2 지점에서 왼쪽이면 왼쪽을 모두 -, 오른쪽이면 오른쪽을 모두 + 하는 방법 => 시간 초과 O(n / 2) +// - 2) Modify 버퍼에 모은 뒤, Sum이 되기 전에 sums에 적용 => 최악의 경우, 한 번씩 번갈아가며 O(500000 * 500000): 약 250초 + +// 세그먼트 트리? => 구현 불가 +// - 요소가 n개인 세그먼트 트리 +// - query, update 두 함수를 만들어야 함 + +// 상수 시간에 누적 값을 채우는 방법? +// - 모든 인덱스에 적용되는 것은 아니라서 하나의 값을 사용하기에는 어려움 +// - 여러 값을 사용하기에는 순회해야 함 + +// 추가할 수 있는 것이 최대 백만 번이다 +// - 0의 개수가 점점 줄어들 것 => 초반의 계산은 노가다? + +// 1 2 3 4 5 +// 0 0 0 1 1 + +// modify를 하면 sums의 해당 인덱스 뒤의 값이 모두 한 번에 더해져야 한다