From 0d6f67a0727b0d32fff0c7d409a55635ebf2fb54 Mon Sep 17 00:00:00 2001 From: myoshizumi Date: Thu, 10 Jul 2025 12:50:03 +0900 Subject: [PATCH 1/2] atcoder B16 - Frog 1 DP --- .../DynamicProgramming/atCoder/B16/B16.go | 113 ++++++++++++ .../DynamicProgramming/atCoder/B16/B16.js | 94 ++++++++++ .../DynamicProgramming/atCoder/B16/B16.php | 100 +++++++++++ .../DynamicProgramming/atCoder/B16/B16.py | 84 +++++++++ .../DynamicProgramming/atCoder/B16/B16.ts | 77 ++++++++ .../DynamicProgramming/atCoder/B16/README.md | 164 ++++++++++++++++++ 6 files changed, 632 insertions(+) create mode 100644 Algorithm/DynamicProgramming/atCoder/B16/B16.go create mode 100644 Algorithm/DynamicProgramming/atCoder/B16/B16.js create mode 100644 Algorithm/DynamicProgramming/atCoder/B16/B16.php create mode 100644 Algorithm/DynamicProgramming/atCoder/B16/B16.py create mode 100644 Algorithm/DynamicProgramming/atCoder/B16/B16.ts create mode 100644 Algorithm/DynamicProgramming/atCoder/B16/README.md diff --git a/Algorithm/DynamicProgramming/atCoder/B16/B16.go b/Algorithm/DynamicProgramming/atCoder/B16/B16.go new file mode 100644 index 00000000..936f4ed4 --- /dev/null +++ b/Algorithm/DynamicProgramming/atCoder/B16/B16.go @@ -0,0 +1,113 @@ +// 以下は、**Go 1.20.6** を用いた「カエルの最小ジャンプコスト」問題の解法です。 +// **実行時間とメモリの消費量を最小限に抑える**ため、\*\*動的計画法(DP)+ 空間最適化(O(1) メモリ)\*\*を使用します。 + +// ## ✅ Go 実装(型明示・最小メモリ・高速) + +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func main() { + reader := bufio.NewReader(os.Stdin) + + // 1行目:N + line1, _ := reader.ReadString('\n') + N, _ := strconv.Atoi(strings.TrimSpace(line1)) + + // 2行目:h[0]~h[N-1] + line2, _ := reader.ReadString('\n') + hStr := strings.Fields(line2) + h := make([]int, N) + for i := 0; i < N; i++ { + h[i], _ = strconv.Atoi(hStr[i]) + } + + if N == 2 { + fmt.Println(abs(h[1] - h[0])) + return + } + + var prev2 int = 0 // dp[i-2] + var prev1 int = abs(h[1] - h[0]) // dp[i-1] + + for i := 2; i < N; i++ { + cost1 := prev1 + abs(h[i]-h[i-1]) + cost2 := prev2 + abs(h[i]-h[i-2]) + curr := min(cost1, cost2) + prev2 = prev1 + prev1 = curr + } + + fmt.Println(prev1) +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} + +// ## ✅ 入出力例 + +// 入力(標準入力): + +// ``` +// 6 +// 30 10 60 10 60 50 +// ``` + +// 出力: + +// ``` +// 40 +// ``` + +// --- + +// ## ✅ 計算量・メモリ量 + +// | 指標 | 値 | +// | ----- | --------------- | +// | 時間計算量 | `O(N)` | +// | 空間計算量 | `O(1)`(定数メモリのみ) | +// | 入力制約 | `2 ≤ N ≤ 10^5` | + +// --- + +// ## ✅ ポイントまとめ + +// * **配列 `dp[]` を使わず**に、`prev1`, `prev2` の2つだけで更新する。 +// * `abs()` でジャンプコストを計算。 +// * `min()` 関数で2通りのジャンプを比較。 + +// --- + +// ## ✅ フルDP版(O(N)メモリ)も参考に: + +// ```go +// dp := make([]int, N) +// dp[0] = 0 +// dp[1] = abs(h[1] - h[0]) +// for i := 2; i < N; i++ { +// dp[i] = min( +// dp[i-1]+abs(h[i]-h[i-1]), +// dp[i-2]+abs(h[i]-h[i-2]), +// ) +// } +// fmt.Println(dp[N-1]) +// ``` + diff --git a/Algorithm/DynamicProgramming/atCoder/B16/B16.js b/Algorithm/DynamicProgramming/atCoder/B16/B16.js new file mode 100644 index 00000000..1780d6bb --- /dev/null +++ b/Algorithm/DynamicProgramming/atCoder/B16/B16.js @@ -0,0 +1,94 @@ +// 以下に、指定された条件(Node.js 18.16.1、`fs` モジュール使用、実行時間・メモリ効率重視)に従って、**カエルの最小コストジャンプ問題**をJavaScriptで解いた実装を示します。 + +// --- + +// ## ✅ アルゴリズム概要(動的計画法DP) + +// * `dp[i]`: 足場 `i` に到達するための最小コスト。 +// * 遷移式: + +// * `dp[i] = min(dp[i-1] + abs(h[i] - h[i-1]), dp[i-2] + abs(h[i] - h[i-2]))` +// * 初期値: + +// * `dp[0] = 0` +// * `dp[1] = abs(h[1] - h[0])` + +// --- + +// ## ✅ JavaScript (Node.js) 実装(`fs` 使用) + +// ```javascript +// const fs = require('fs'); + +// function main(input) { +// const lines = input.trim().split('\n'); +// const N = parseInt(lines[0], 10); +// const h = lines[1].split(' ').map(Number); + +// const dp = new Array(N).fill(0); +// dp[0] = 0; +// dp[1] = Math.abs(h[1] - h[0]); + +// for (let i = 2; i < N; i++) { +// dp[i] = Math.min( +// dp[i - 1] + Math.abs(h[i] - h[i - 1]), +// dp[i - 2] + Math.abs(h[i] - h[i - 2]) +// ); +// } + +// console.log(dp[N - 1]); +// } + +// // 標準入力から読み込む +// main(fs.readFileSync('/dev/stdin', 'utf8')); +// ``` + +// --- + +// ## ✅ 計算量・メモリ使用量 + +// * **時間計算量**: `O(N)`(1回ずつループ) +// * **空間計算量**: `O(N)`(DP配列1本) + +// * さらに最適化すれば `O(1)` でも可能(直近2要素のみ使用) + +// --- + +// ## ✅ 最適化バージョン(メモリ `O(1)`) + +// ```javascript +const fs = require('fs'); + +function main(input) { + const lines = input.trim().split('\n'); + const N = parseInt(lines[0], 10); + const h = lines[1].split(' ').map(Number); + + let prev2 = 0; // dp[i-2] + let prev1 = Math.abs(h[1] - h[0]); // dp[i-1] + + for (let i = 2; i < N; i++) { + const curr = Math.min( + prev1 + Math.abs(h[i] - h[i - 1]), + prev2 + Math.abs(h[i] - h[i - 2]) + ); + prev2 = prev1; + prev1 = curr; + } + + console.log(prev1); +} + +main(fs.readFileSync('/dev/stdin', 'utf8')); + +// ## ✅ 入出力例テスト(例1) + +// ``` +// 入力: +// 4 +// 10 30 40 20 + +// 出力: +// 30 +// ``` + diff --git a/Algorithm/DynamicProgramming/atCoder/B16/B16.php b/Algorithm/DynamicProgramming/atCoder/B16/B16.php new file mode 100644 index 00000000..ddb5271a --- /dev/null +++ b/Algorithm/DynamicProgramming/atCoder/B16/B16.php @@ -0,0 +1,100 @@ +