สมมติว่าเรามีรายการของตัวเลขที่ไม่ซ้ำกันและเรียงลำดับที่แสดงถึงเบรกพอยต์ในสตริง เราต้องการสร้างต้นไม้จากกฎเหล่านี้ -
-
มีโหนดที่มีค่า (a, b) โดยที่ a และ b เป็นเบรกพอยต์ ซึ่งหมายความว่าโหนดมีช่วงจากดัชนี [a, b] ในสตริง
-
โหนดรูทครอบคลุมทุกเบรกพอยต์ (ทั้งสตริง)
-
สแปนของโหนดย่อยซ้ายและขวาถูกเรียงลำดับ ต่อเนื่องกัน และมีสแปนของโหนดหลัก
-
ดัชนีของโหนดลีฟของ 'a' ในเบรกพอยต์คือ 1 ก่อนดัชนีของ 'b' ในส่วนเบรกพอยต์
ราคาของต้นไม้ถูกกำหนดเป็นผลรวมของ b - a สำหรับทุกโหนดในทรี เป้าหมายของเราคือการกำหนดราคาต้นไม้ที่เป็นไปได้ต่ำที่สุดเท่าที่จะเป็นไปได้
ดังนั้น หากอินพุตเป็นเหมือนเบรกพอยต์ =[1, 4, 7, 12] เอาต์พุตจะเป็น 28
เพื่อแก้ปัญหานี้ เราจะทำตามขั้นตอนเหล่านี้ -
-
n :=ขนาดของเบรกพอยต์อาร์เรย์อินพุต
-
ถ้า n <=1 แล้ว −
-
คืนค่า 0
-
-
ถ้า n เท่ากับ 2 แล้ว −
-
จุดพักกลับ[1] - จุดพัก[0]
-
-
กำหนดอาร์เรย์ p[n - 1]
-
สำหรับการเริ่มต้น i :=0 เมื่อ i
-
p[i] :=เบรกพอยต์[i + 1]
-
-
กำหนดอาร์เรย์ก่อน[n]
-
สำหรับการเริ่มต้น i :=1 เมื่อฉัน
-
pre[i] :=pre[i - 1] + p[i - 1]
-
-
กำหนดอาร์เรย์ 2 มิติ dp[n, n] หนึ่งรายการและเริ่มต้นคอลัมน์ด้วยความไม่มีที่สิ้นสุด
-
กำหนดอาร์เรย์ 2 มิติ op[n, n]
-
สำหรับการเริ่มต้น i :=1 เมื่อฉัน
-
dp[i,i] :=p[i - 1], op[i,i] :=ผม
-
-
สำหรับการเริ่มต้น len :=2 เมื่อ len
-
สำหรับการเริ่มต้น i :=1 เมื่อ i + len - 1
-
j :=i + len - 1
-
idx :=ผม
-
สำหรับการเริ่มต้น k :=สูงสุดของ(i, op[i,j-1]) เมื่อ k <ขั้นต่ำของ (j - 1, op[i + 1, j]), อัปเดต (เพิ่ม k ขึ้น 1) ทำ:
-
ราคา :=dp[i, k] + dp[k + 1, j]
-
ถ้าราคา
-
idx :=k
-
dp[i, j] :=ต้นทุน
-
-
-
op[i, j] :=idx
-
dp[i, j] :=dp[i, j] + ก่อน[j] - ก่อน[i - 1]
-
-
-
กลับ dp[1, n - 1]
ตัวอย่าง
ให้เราดูการใช้งานต่อไปนี้เพื่อความเข้าใจที่ดีขึ้น -
#include <bits/stdc++.h>
using namespace std;
int solve(vector<int>& breakpoints) {
int n = breakpoints.size();
if (n <= 1) return 0;
if (n == 2) return breakpoints[1] - breakpoints[0];
vector<int> p(n - 1);
for (int i = 0; i < n - 1; ++i) p[i] = breakpoints[i + 1] - breakpoints[i];
vector<int> pre(n);
for (int i = 1; i < n; ++i) pre[i] = pre[i - 1] + p[i - 1];
vector<vector<int>> dp(n, vector<int>(n, INT_MAX));
vector<vector<int>> op(n, vector<int>(n));
for (int i = 1; i < n; ++i) dp[i][i] = p[i - 1], op[i][i] = i;
for (int len = 2; len < n; ++len) {
for (int i = 1; i + len - 1 < n; ++i) {
int j = i + len - 1;
int idx = i;
for (int k = max(i, op[i][j - 1]); k <= min(j - 1, op[i + 1][j]); ++k) {
int cost = dp[i][k] + dp[k + 1][j];
if (cost < dp[i][j]) {
idx = k;
dp[i][j] = cost;
}
}
op[i][j] = idx;
dp[i][j] += pre[j] - pre[i - 1];
}
}
return dp[1][n - 1];
}
int main(){
vector<int> breakpoints = {1, 4, 7, 12};
cout << solve(breakpoints) << endl;
return 0;
} อินพุต
{1, 4, 7, 12} ผลลัพธ์
28