Problem:
Optimal Binary Search Tree
Optimal Binary Search Tree is a binary search tree constructed from $n$ keys and $n+1$ dummy keys so as to minimize the expected value of cost for a search operation.
We are given a sequence $K = {k_1, k_2, ..., k_n}$ of $n$ distinct keys in sorted order $(k_1 < k_2 < ... < k_n)$, and we wish to construct a binary search tree. For each key $k_i$, we have a probability $p_i$ that a search will be for $k_i$. Some searches may be for values not in $K$, and so we also have $n+1$ dummy keys $d_0, d_1, d_2, ..., d_n$ representing values not in $K$. The dummy keys $d_i (0 \le i \le n)$ are defined as follows:
if $i=0$, then $d_i$ represents all values less than $k_1$
if $i=n$, then $d_i$ represents all values greater than $k_n$
if $1 \le i \le n-1$, then $d_i$ represents all values between $k_i$ and $k_{i+1}$
For each dummy key $d_i$, we have a probability $q_i$ that a search will correspond to $d_i$.
For $p_i (1 \le i \le n)$ and $q_i (0 \le i \le n)$, we have 

  \[
  \sum_{i=1}^n p_i + \sum_{i=0}^n q_i = 1
  \]

  Then the expected cost of a search in a binary search tree $T$ is

  \[
  E_T = \sum_{i=1}^n (depth_T(k_i) + 1) \cdot p_i + \sum_{i=0}^n (depth_T(d_i) + 1) \cdot q_i
  \]

  where $depth_T(v)$ is the depth of node $v$ in $T$.

  For a given set of probabilities, our goal is to construct a binary search tree whose expected search cost is smallest. We call such a tree an
optimal binary search tree
.
Each key $k_i$ is an internal node and each dummy key $d_i$ is a leaf. For example, the following figure shows the optimal binary search tree obtained from Sample Input 1.
Task
Write a program which calculates the expected value of a search operation on the optimal binary search tree obtained by given $p_i$ that a search will be for $k_i$ and $q_i$ that a search will correspond to $d_i$.
Input
$n$
$p_1$ $p_2$ ... $p_n$
$q_0$ $q_1$ $q_2$ ... $q_n$
In the first line, an integer $n$ which represents the number of keys is given.
In the second line, $p_i (1 \le i \le n)$ are given in real numbers with four decimal places.
In the third line, $q_i (0 \le i \le n)$ are given in real numbers with four decimal places.
Output
Print the expected value for a search operation on the optimal binary search tree in a line.
The output must not contain an error greater than $10^{−4}$.
Constraints
$1 \le n \le 500$
$0 \lt p_i, q_i \lt 1$
$\displaystyle \sum_{i=1}^n p_i + \sum_{i=0}^n q_i = 1$
Sample Input 1
5
0.1500 0.1000 0.0500 0.1000 0.2000
0.0500 0.1000 0.0500 0.0500 0.0500 0.1000
Sample Output 1
2.75000000
Sample Input 2
7
0.0400 0.0600 0.0800 0.0200 0.1000 0.1200 0.1400
0.0600 0.0600 0.0600 0.0600 0.0500 0.0500 0.0500 0.0500
Sample Output 2
3.12000000

Submitted solutions:

code_snippet: //
// Created by Manas Choudhary on 04-11-2025 05:05 PM
//
#include <algorithm>
#include <iostream>
#include <chrono>
#include <vector>
#include <cmath>
#include <unordered_map>
#include <map>
#include <queue>
#define ll long double
#define ld long double
#define umap unordered_map
#define vec(type) vector<type>
#define pb push_back
#define all(v) v.begin(), v.end()
#define sz(v) (int)(v).size()
#define vecout(v) for (auto &x : v) cout << x << ' '; cout << '\n';
#define fastio() ios::sync_with_stdio(false); cin.tie(nullptr);
#define yes cout << "YES\n"
#define no cout << "NO\n"

using namespace std;
using namespace chrono;

const int INF = 1e9;
const long long LINF = 1e18;
const int MOD = 1e9 + 7;
const double pi = acos(-1);



#include <iomanip> // Make sure to add this header

int solve() {
    long long n;
    cin >> n;
    vec(ld) k(n+1,0);
    vec(ld) d(n+1,0);

    // 1. INPUT (Assuming this is fixed now)
    for (int i = 1; i <= n; i++) {
        cin >> k[i];
    }
    for (int i = 0; i <= n; i++) {
        cin >> d[i];
    }

    // 2. PREFIX SUMS (This part is correct)
    vec(ld) pk(n+1,0);
    for (int i = 1; i <= n; i++) {
        pk[i] = pk[i-1] + k[i];
    }
    vec(ld) pd(n+2,0);
    for (int i = 0; i < n + 1; i++) {
        pd[i+1] = pd[i] + d[i];
    }
    auto getsumk = [& pk](int i,int j)->ld{
        if (i > j) return 0; // Handle empty range
        return pk[j]-pk[i-1];
    };
    auto getsumd = [& pd](int i , int j)->ld {
        if (i > j) return 0; // Handle empty range
        return pd[j+1]-pd[i];
    };

    // 3. DP TABLE (FIX A: Make size n+2 by n+2)
    // We need to access dp[1][0] through dp[n+1][n]
    vec(vec(ld)) dp(n+2, vector<ld>(n+2, 0));

    // 4. BASE CASES (FIX B: Initialize empty trees)
    // dp[i][i-1] = cost of dummy key d[i-1]
    for (int i = 1; i <= n + 1; i++) {
        // getsumd(i-1, i-1) = pd[i] - pd[i-1] = d[i-1]
        dp[i][i-1] = getsumd(i-1, i-1);
    }

    // 5. MAIN DP LOOP
    for (int l = 1; l <= n; l++) {
        for (int i = 1; i <= n - l + 1; i++) {
            int j = i + l - 1;

            // This is the cost w(i,j)
            ld w_ij = getsumk(i, j) + getsumd(i - 1, j);

            // Start with a very high cost
            dp[i][j] = 1e18; // Use LINF or 1e18

            // k is the root
            for (int k = i; k <= j; k++) {

                // FIX C: No more ternary. Use the base cases.
                ld left = dp[i][k-1];  // Cost of left tree (uses dp[i][i-1] when k=i)
                ld right = dp[k+1][j]; // Cost of right tree (uses dp[j+1][j] when k=j)

                // The recurrence:
                // dp[i][j] = min(dp[i][j], left + right);
                // We add w_ij ONCE, after the loop
                dp[i][j] = min(dp[i][j], left + right);
            }

            // FIX D: Add the w(i,j) cost *after* finding the min
            dp[i][j] += w_ij;
        }
    }

    // 6. OUTPUT (FIX E: Add precision)
    cout << fixed << setprecision(12) << dp[1][n] << endl ;

    return 0;
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    auto start = high_resolution_clock::now();


    int t=1;
    while (t--) {
        solve();
    }

   
    auto end = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(end - start);
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 7128
final_rank: 15

code_snippet: //
// Created by Manas Choudhary on 04-11-2025 05:05 PM
//
#include <algorithm>
#include <iostream>
#include <chrono>
#include <vector>
#include <cmath>
#include <unordered_map>
#include <map>
#include <queue>
#define ll long double
#define ld long double
#define umap unordered_map
#define vec(type) vector<type>
#define pb push_back
#define all(v) v.begin(), v.end()
#define sz(v) (int)(v).size()
#define vecout(v) for (auto &x : v) cout << x << ' '; cout << '\n';
#define fastio() ios::sync_with_stdio(false); cin.tie(nullptr);
#define yes cout << "YES\n"
#define no cout << "NO\n"

using namespace std;
using namespace chrono;

const int INF = 1e9;
const long long LINF = 1e18;
const int MOD = 1e9 + 7;
const double pi = acos(-1);



#include <iomanip> // Make sure to add this header

int solve() {
    long long n;
    cin >> n;
    vec(ld) k(n+1,0);
    vec(ld) d(n+1,0);

    // 1. INPUT (Assuming this is fixed now)
    for (int i = 1; i <= n; i++) {
        cin >> k[i];
    }
    for (int i = 0; i <= n; i++) {
        cin >> d[i];
    }

    // 2. PREFIX SUMS (This part is correct)
    vec(ld) pk(n+1,0);
    for (int i = 1; i <= n; i++) {
        pk[i] = pk[i-1] + k[i];
    }
    vec(ld) pd(n+2,0);
    for (int i = 0; i < n + 1; i++) {
        pd[i+1] = pd[i] + d[i];
    }
    auto getsumk = [& pk](int i,int j)->ld{
        if (i > j) return 0; // Handle empty range
        return pk[j]-pk[i-1];
    };
    auto getsumd = [& pd](int i , int j)->ld {
        if (i > j) return 0; // Handle empty range
        return pd[j+1]-pd[i];
    };

    // 3. DP TABLE (FIX A: Make size n+2 by n+2)
    // We need to access dp[1][0] through dp[n+1][n]
    vec(vec(ld)) dp(n+2, vector<ld>(n+2, 0));

    // 4. BASE CASES (FIX B: Initialize empty trees)
    // dp[i][i-1] = cost of dummy key d[i-1]
    for (int i = 1; i <= n + 1; i++) {
        // getsumd(i-1, i-1) = pd[i] - pd[i-1] = d[i-1]
        dp[i][i-1] = getsumd(i-1, i-1);
    }

    // 5. MAIN DP LOOP
    for (int l = 1; l <= n; l++) {
        for (int i = 1; i <= n - l + 1; i++) {
            int j = i + l - 1;

            // This is the cost w(i,j)
            ld w_ij = getsumk(i, j) + getsumd(i - 1, j);

            // Start with a very high cost
            dp[i][j] = 1e18; // Use LINF or 1e18

            // k is the root
            for (int k = i; k <= j; k++) {

                // FIX C: No more ternary. Use the base cases.
                ld left = dp[i][k-1];  // Cost of left tree (uses dp[i][i-1] when k=i)
                ld right = dp[k+1][j]; // Cost of right tree (uses dp[j+1][j] when k=j)

                // The recurrence:
                // dp[i][j] = min(dp[i][j], left + right);
                // We add w_ij ONCE, after the loop
                dp[i][j] = min(dp[i][j], left + right);
            }

            // FIX D: Add the w(i,j) cost *after* finding the min
            dp[i][j] += w_ij;
        }
    }

    // 6. OUTPUT (FIX E: Add precision)
    cout << fixed << setprecision(12) << dp[1][n] ;

    return 0;
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    auto start = high_resolution_clock::now();


    int t=1;
    while (t--) {
        solve();
    }

   
    auto end = high_resolution_clock::now();
    auto duration = duration_cast<microseconds>(end - start);
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 7068
final_rank: 13

code_snippet: #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 1000
int n;
double p[MAXN + 5], q[MAXN + 5];
double dp[MAXN + 5][MAXN + 5];
double w[MAXN + 5][MAXN + 5];
int seg[MAXN + 5][MAXN + 5];
double calc(int l, int r, int d) {
    if (l == r + 1)
        return q[r] * d;
    return calc(l, seg[l][r] - 1, d + 1) + calc(seg[l][r] + 1, r, d + 1) + p[seg[l][r]] * d;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%lf", &p[i]);
    for (int i = 0; i <= n; ++i)
        scanf("%lf", &q[i]);
    for (int i = 0; i <= n + 1; ++i)
        for (int j = 0; j <= n + 1; ++j)
            dp[i][j] = 1e20;
    memset(w, 0, sizeof w);
    for (int i = 1; i <= n; ++i)
        w[i][i - 1] = q[i - 1];
    for (int i = 0; i <= n; ++i)
        dp[i][i - 1] = dp[i + 1][i] = 0;
    for (int len = 1; len <= n; ++len)
        for (int l = 1; l + len - 1 <= n; ++l) {
            int r = l + len - 1;
            w[l][r] = w[l][r - 1] + p[r] + q[r];
            for (int k = l; k <= r; ++k) {
                auto val = dp[l][k - 1] + dp[k + 1][r] + w[l][r];
                if (val < dp[l][r]) {
                    dp[l][r] = val;
                    seg[l][r] = k;
                }
            }
        }
    printf("%.6lf", calc(1, n, 1));
}
accuracy: 1
time_ms: 20
memory_kb: 19304
final_rank: 18

code_snippet: #include <iostream>
#include <vector>
#include <iomanip>
#include <limits>
using namespace std;

int main() {
    int n;
    cin >> n;
    vector<double> p(n), q(n+1);
    for (int i = 0; i < n; i++) cin >> p[i];
    for (int i = 0; i <= n; i++) cin >> q[i];

    vector<vector<double>> e(n+2, vector<double>(n+2, 0));
    vector<vector<double>> w(n+2, vector<double>(n+2, 0));
    for (int i = 0; i <= n; ++i) {
        e[i][i] = q[i];
        w[i][i] = q[i];
    }
    for (int l = 1; l <= n; ++l) {
        for (int i = 0; i <= n-l; ++i) {
            int j = i+l;
            e[i][j] = numeric_limits<double>::infinity();
            w[i][j] = w[i][j-1]+p[j-1]+q[j];
            for (int r = i; r < j; ++r) {
                double t = e[i][r]+e[r+1][j]+w[i][j];
                if (t < e[i][j]) {
                    e[i][j] = t;
                }
            }
        }
    }

    cout << fixed << setprecision(8) << e[0][n] << endl;

    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 7484
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define loop(n) for (int tjh = 0; tjh < (int)(n); ++tjh)
constexpr double INF=1e100;
signed main() {
  cin.tie(0)->sync_with_stdio(0);
  cout<<fixed<<setprecision(16);
  int n;cin>>n;vector<double>a(2*n+1);
  rep(i,n)cin>>a[i*2+1];
  rep(i,n+1)cin>>a[i*2];
  vector<double>a0(2*n+2);
  partial_sum(a.begin(), a.end(),a0.begin()+1);
  vector dp(n+1,vector<double>(n+1));
  rep(i,n+1)dp[i][i]=a[i*2];
  for (int l=1;l<=n;++l) {
    rep(i,n-l+1) {
      const int j{i+l};
      dp[i][j]=INF;
      for (int k=i;k<j;++k) {
        double te1{dp[i][k]+dp[k+1][j]};
        if (te1<dp[i][j])dp[i][j]=te1;
      }
      dp[i][j]+=a0[j*2+1]-a0[i*2];
    }
  }
  cout<<dp[0][n]<<'\n';
}
accuracy: 1
time_ms: 20
memory_kb: 5632
final_rank: 1

code_snippet: #include <stdio.h>

#define MAX 500 // 最大のキーの個数
#define INF 1e6 // 非常に大きな値

double e[MAX + 1][MAX + 1]; // 部分木の期待コスト
double w[MAX + 1][MAX + 1]; // 部分木の確率の合計
double root[MAX + 1][MAX + 1]; // 部分木の根ノード

double minCost(int n, double p[], double q[]) {
    // 配列初期化
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= n; j++) {
            e[i][j] = 0.0;
            w[i][j] = 0.0;
        }
    }

    // 初期化
    for (int i = 0; i <= n; i++) {
        e[i][i] = q[i];
        w[i][i] = q[i];
    }

    // 動的計画法によるコスト計算
    for (int l = 1; l <= n; l++) { // 部分木の長さ
        for (int i = 0; i <= n - l; i++) {
            int j = i + l;
            e[i][j] = INF;
            w[i][j] = w[i][j - 1] + p[j - 1] + q[j];

            // 最小コストを計算
            for (int r = i + 1; r <= j; r++) {
                double cost = e[i][r - 1] + e[r][j] + w[i][j];
                if (cost < e[i][j]) {
                    e[i][j] = cost;
                    root[i][j] = r;
                }
            }
        }
    }

    return e[0][n];
}

int main() {
    int n;
    double p[MAX], q[MAX];

    // 入力
    scanf("%d", &n);
    if (n > MAX || n <= 0) {
        printf("Error: Invalid number of keys.\n");
        return 1;
    }

    for (int i = 0; i < n; i++) {
        scanf("%lf", &p[i]);
    }
    for (int i = 0; i <= n; i++) {
        scanf("%lf", &q[i]);
    }

    // 最適探索コストの計算
    double result = minCost(n, p, q);

    // 出力
    printf("%.8lf\n", result);

    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 8812
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>
#include <string.h>
#include <set>
#include <map>
//#include <atcoder/all>

using namespace std;
//using namespace atcoder;


static const int MAX = 550;


float P[MAX], Q[MAX];
float minCostArray[MAX][MAX];
float SumArray_P[MAX], SumArray_Q[MAX];

float SumOfProp(int x, int y) {
	if (x == 1) {
		return SumArray_P[y] + SumArray_Q[y];
	}
	else {
		return (SumArray_P[y] - SumArray_P[x - 1]) + (SumArray_Q[y] - SumArray_Q[x - 2]);
	}
}

float CalcCost(int i, int j){

	if (minCostArray[i][j] != -1) {
		return minCostArray[i][j];
	}


	float minC = 1000000000;
	if (i - 1 == j ) {
		minC = Q[i - 1];
	}
	else {
		for (int r = i; r <= j; r++) {
			minC = min(minC, CalcCost(i, r - 1) + CalcCost(r + 1, j) + SumOfProp(i, j));
		}
	}

	minCostArray[i][j] = minC;
	return minC;

}


int main() {

	for (int i = 0; i < MAX; i++) {
		for(int j = 0; j < MAX; j++) {
			minCostArray[i][j] = -1;
		}
	}

	int n;
	cin >> n;

	SumArray_P[0] = SumArray_Q[0] = 0;

	for (int i = 1; i <= n; i++) {
		cin >> P[i];
		SumArray_P[i] = SumArray_P[i - 1] + P[i];
	}
	for (int i = 0; i <= n; i++) {
		cin >> Q[i];
		if (i == 0) SumArray_Q[i] = Q[i];
		else SumArray_Q[i] = SumArray_Q[i - 1] + Q[i];
	}

	cout << CalcCost(1, n) << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 4788
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <string>
#include <string.h>
#include <set>
#include <map>
//#include <atcoder/all>

using namespace std;
//using namespace atcoder;


static const int MAX = 501;


float P[MAX], Q[MAX];
float minCostArray[MAX][MAX];
float SumArray_P[MAX], SumArray_Q[MAX];

float SumOfProp(int x, int y) {
	if (x == 1) {
		return SumArray_P[y] + SumArray_Q[y];
	}
	else {
		return (SumArray_P[y] - SumArray_P[x - 1]) + (SumArray_Q[y] - SumArray_Q[x - 2]);
	}
}

float CalcCost(int i, int j){

	if (minCostArray[i][j] != -1) {
		return minCostArray[i][j];
	}


	float minC = 100000000;
	if (i - 1 == j ) {
		minC = Q[i - 1];
	}
	else {
		for (int r = i; r <= j; r++) {
			minC = min(minC, CalcCost(i, r - 1) + CalcCost(r + 1, j) + SumOfProp(i, j));
		}
	}

	minCostArray[i][j] = minC;
	return minC;

}


int main() {

	for (int i = 0; i < MAX; i++) {
		for(int j = 0; j < MAX; j++) {
			minCostArray[i][j] = -1;
		}
	}

	int n;
	cin >> n;

	SumArray_P[0] = SumArray_Q[0] = 0;

	for (int i = 1; i <= n; i++) {
		cin >> P[i];
		SumArray_P[i] = SumArray_P[i - 1] + P[i];
	}
	for (int i = 0; i <= n; i++) {
		cin >> Q[i];
		if (i == 0) SumArray_Q[i] = Q[i];
		else SumArray_Q[i] = SumArray_Q[i - 1] + Q[i];
	}

	cout << CalcCost(1, n) << endl;
}
accuracy: 0.9333333333333333
time_ms: 60
memory_kb: 4548
final_rank: 20

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
#include <limits>
using namespace std;

// 各範囲のキーのコストの合計を求める
vector<vector<double>> setKeySumCost(const vector<double> &array_k, const vector<double> &array_d)
{
    int n = array_d.size();
    vector<vector<double>> keySumCost(n);
    for (int i = 0; i < n; i++)
    {
        keySumCost[i].resize(n);
        keySumCost[i][i] = array_d[i];
        for (int j = i + 1; j < n; j++)
        {
            keySumCost[i][j] = keySumCost[i][j - 1] + array_k[j - 1] + array_d[j];
        }
    }
    return keySumCost;
}

// 最小のコストを求める
double getMinCost(const vector<vector<double>> &keySumCost)
{
    int n = keySumCost.size();
    vector<vector<double>> optCost(n);

    // ダミーキー単体のコストを設定
    for (int i = 0; i < n; i++)
    {
        optCost[i].resize(n);
        optCost[i][i] = keySumCost[i][i];
    }

    // 範囲の長さを指定
    // 最初は短い範囲から、最後は全体の範囲で最小のコストを求める
    for (int len = 1; len < n; len++)
    {
        // 起点を設定する
        // 最初は k1~k2, k2~k3
        for (int begin = 0; begin < n - len; begin++)
        {
            // 範囲内でどのキーを中央にすると最小のコストになるか求める
            double minSum = std::numeric_limits<double>::infinity();
            for (int r = begin + 1; r <= begin + len; r++)
            {
                double tmpSum = optCost[begin][r - 1] + optCost[r][begin + len];
                // double left = optCost[begin][r - 1];
                // double right = optCost[r][begin + len];
                if (tmpSum < minSum)
                {
                    minSum = tmpSum;
                }
            }
            optCost[begin][begin + len] = keySumCost[begin][begin + len] + minSum;
        }
    }

    return optCost[0][n - 1];
}

int main()
{
    int n;
    cin >> n;
    vector<double> array_k;
    vector<double> array_d;
    for (int i = 0; i < n; i++)
    {
        double num;
        cin >> num;
        array_k.push_back(num);
    }
    for (int i = 0; i < n + 1; i++)
    {
        double num;
        cin >> num;
        array_d.push_back(num);
    }
    vector<vector<double>> keySumCost = setKeySumCost(array_k, array_d);
    double minCost = getMinCost(keySumCost);
    cout << fixed << setprecision(12) << minCost << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 7100
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
#include <limits>
using namespace std;

// 各範囲のキーのコストの合計を求める
vector<vector<double>> setKeySumCost(const vector<double> &array_k, const vector<double> &array_d)
{
    int n = array_k.size() + 1;
    vector<vector<double>> keySumCost(n);
    for (int i = 0; i < n; i++)
    {
        keySumCost[i].resize(n);
        keySumCost[i][i] = array_d[i];
        for (int j = i + 1; j < n; j++)
        {
            keySumCost[i][j] = keySumCost[i][j - 1] + array_k[j - 1] + array_d[j];
        }
    }
    return keySumCost;
}

// 最小のコストを求める
double getMinCost(const vector<vector<double>> &keySumCost)
{
    int n = keySumCost.size();
    vector<vector<double>> optCost(n);

    // ダミーキー単体のコストを設定
    for (int i = 0; i < n; i++)
    {
        optCost[i].resize(n);
        optCost[i][i] = keySumCost[i][i];
    }
    // 内部節点の下にダミーキーしかない時のコストを求める
    // for (int i = 0; i < n - 1; i++)
    // {
    //     optCost[i][i + 1] = keySumCost[i][i + 1] + optCost[i][i] + optCost[i + 1][i + 1];
    // }

    // 範囲の長さを指定
    // 最初は短い範囲から、最後は全体の範囲で最小のコストを求める
    for (int len = 1; len < n; len++)
    {
        // 起点を設定する
        // 最初は k1~k2, k2~k3
        for (int begin = 0; begin < n - len; begin++)
        {
            // 範囲内でどのキーを中央にすると最小のコストになるか求める
            double minSum = std::numeric_limits<double>::infinity();
            for (int r = begin + 1; r <= begin + len; r++)
            {
                double tmpSum = optCost[begin][r - 1] + optCost[r][begin + len];
                // double left = optCost[begin][r - 1];
                // double right = optCost[r][begin + len];
                if (tmpSum < minSum)
                {
                    minSum = tmpSum;
                }
            }
            optCost[begin][begin + len] = keySumCost[begin][begin + len] + minSum;
        }
    }

    return optCost[0][n - 1];
}

int main()
{
    int n;
    cin >> n;
    vector<double> array_k;
    vector<double> array_d;
    for (int i = 0; i < n; i++)
    {
        double num;
        cin >> num;
        array_k.push_back(num);
    }
    for (int i = 0; i < n + 1; i++)
    {
        double num;
        cin >> num;
        array_d.push_back(num);
    }
    vector<vector<double>> keySumCost = setKeySumCost(array_k, array_d);
    double minCost = getMinCost(keySumCost);
    cout << fixed << setprecision(12) << minCost << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 7056
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
#include <limits>
using namespace std;

// 各範囲のキーのコストの合計を求める
vector<vector<double>> setKeySumCost(const vector<double> &array_k, const vector<double> &array_d)
{
    int n = array_k.size() + 1;
    vector<vector<double>> keySumCost(n);
    for (int i = 0; i < n; i++)
    {
        keySumCost[i].resize(n);
        keySumCost[i][i] = array_d[i];
        for (int j = i + 1; j < n; j++)
        {
            keySumCost[i][j] = keySumCost[i][j - 1] + array_k[j - 1] + array_d[j];
        }
    }
    return keySumCost;
}

// 最小のコストを求める
double getMinCost(const vector<vector<double>> &keySumCost)
{
    int n = keySumCost.size();
    vector<vector<double>> optCost(n);

    // ダミーキー単体のコストを設定
    for (int i = 0; i < n; i++)
    {
        optCost[i].resize(n);
        optCost[i][i] = keySumCost[i][i];
    }
    // 内部節点の下にダミーキーしかない時のコストを求める
    for (int i = 0; i < n - 1; i++)
    {
        optCost[i][i + 1] = keySumCost[i][i + 1] + optCost[i][i] + optCost[i + 1][i + 1];
    }

    // 範囲の長さを指定
    // 最初は短い範囲から、最後は全体の範囲で最小のコストを求める
    for (int len = 2; len < n; len++)
    {
        // 起点を設定する
        // 最初は k1~k2, k2~k3
        for (int begin = 0; begin < n - len; begin++)
        {
            // 範囲内でどのキーを中央にすると最小のコストになるか求める
            double minSum = std::numeric_limits<double>::infinity();
            for (int r = begin + 1; r <= begin + len; r++)
            {
                double tmpSum = optCost[begin][r - 1] + optCost[r][begin + len];
                // double left = optCost[begin][r - 1];
                // double right = optCost[r][begin + len];
                if (tmpSum < minSum)
                {
                    minSum = tmpSum;
                }
            }
            optCost[begin][begin + len] = keySumCost[begin][begin + len] + minSum;
        }
    }

    return optCost[0][n - 1];
}

int main()
{
    int n;
    cin >> n;
    vector<double> array_k;
    vector<double> array_d;
    for (int i = 0; i < n; i++)
    {
        double num;
        cin >> num;
        array_k.push_back(num);
    }
    for (int i = 0; i < n + 1; i++)
    {
        double num;
        cin >> num;
        array_d.push_back(num);
    }
    vector<vector<double>> keySumCost = setKeySumCost(array_k, array_d);
    double minCost = getMinCost(keySumCost);
    cout << fixed << setprecision(12) << minCost << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 7056
final_rank: 2

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;

// 各範囲のキーのコストの合計を求める
vector<vector<double>> setKeySumCost(const vector<double> &array_k, const vector<double> &array_d)
{
    int n = array_k.size() + 1;
    vector<vector<double>> keySumCost(n);
    for (int i = 0; i < n; i++)
    {
        keySumCost[i].resize(n);
        keySumCost[i][i] = array_d[i];
        for (int j = i + 1; j < n; j++)
        {
            keySumCost[i][j] = keySumCost[i][j - 1] + array_k[j - 1] + array_d[j];
        }
    }
    return keySumCost;
}

// 最小のコストを求める
double getMinCost(const vector<vector<double>> &keySumCost)
{
    int n = keySumCost.size();
    vector<vector<double>> optCost(n);

    // ダミーキー単体のコストを設定
    for (int i = 0; i < n; i++)
    {
        optCost[i].resize(n);
        optCost[i][i] = keySumCost[i][i];
    }
    // 内部節点の下にダミーキーしかない時のコストを求める
    for (int i = 0; i < n - 1; i++)
    {
        optCost[i][i + 1] = keySumCost[i][i + 1] + optCost[i][i] + optCost[i + 1][i + 1];
    }

    // 範囲の長さを指定
    // 最初は短い範囲から、最後は全体の範囲で最小のコストを求める
    for (int len = 2; len < n; len++)
    {
        // 起点を設定する
        // 最初は k1~k2, k2~k3
        for (int begin = 0; begin < n - len; begin++)
        {
            // 範囲内でどのキーを中央にすると最小のコストになるか求める
            vector<double> sums;
            for (int r = begin + 1; r <= begin + len; r++)
            {
                double left = optCost[begin][r - 1];
                double right = optCost[r][begin + len];
                sums.push_back(left + right);
            }
            vector<double>::iterator iter = min_element(sums.begin(), sums.end());
            size_t index = distance(sums.begin(), iter);
            optCost[begin][begin + len] = keySumCost[begin][begin + len] + sums[index];
        }
    }

    return optCost[0][n - 1];
}

int main()
{
    int n;
    cin >> n;
    vector<double> array_k;
    vector<double> array_d;
    for (int i = 0; i < n; i++)
    {
        double num;
        cin >> num;
        array_k.push_back(num);
    }
    for (int i = 0; i < n + 1; i++)
    {
        double num;
        cin >> num;
        array_d.push_back(num);
    }
    vector<vector<double>> keySumCost = setKeySumCost(array_k, array_d);
    double minCost = getMinCost(keySumCost);
    cout << fixed << setprecision(12) << minCost << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 7100
final_rank: 14

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;

// 各範囲のキーのコストの合計を求める
vector<vector<double>> setKeySumCost(const vector<double> &array_k, const vector<double> &array_d)
{
    int n = array_k.size() + 1;
    vector<vector<double>> keySumCost(n);
    for (int i = 0; i < n; i++)
    {
        keySumCost[i].resize(n);
        keySumCost[i][i] = array_d[i];
        for (int j = i + 1; j < n; j++)
        {
            keySumCost[i][j] = keySumCost[i][j - 1] + array_k[j - 1] + array_d[j];
        }
    }
    return keySumCost;
}

// 最小のコストを求める
double getMinCost(const vector<vector<double>> &keySumCost)
{
    int n = keySumCost.size();
    vector<vector<double>> optCost(n);

    // ダミーキー単体のコストを設定
    for (int i = 0; i < n; i++)
    {
        optCost[i].resize(n);
        optCost[i][i] = keySumCost[i][i];
    }
    // 内部節点の下にダミーキーしかない時のコストを求める
    for (int i = 0; i < n - 1; i++)
    {
        optCost[i][i + 1] = keySumCost[i][i + 1] + optCost[i][i] + optCost[i + 1][i + 1];
    }

    // 範囲の長さを指定
    // 最初は短い範囲から、最後は全体の範囲で最小のコストを求める
    for (int len = 2; len < n; len++)
    {
        // 起点を設定する
        // 最初は k1~k2, k2~k3
        for (int begin = 0; begin < n - len; begin++)
        {
            // 範囲内でどのキーを中央にすると最小のコストになるか求める
            vector<double> sums;
            for (int r = begin + 1; r <= begin + len; r++)
            {
                double left = begin + 1 < r ? optCost[begin][r - 1] : optCost[begin][begin];
                double right = r < begin + len ? optCost[r][begin + len] : optCost[begin + len][begin + len];
                sums.push_back(left + right);
            }
            vector<double>::iterator iter = min_element(sums.begin(), sums.end());
            size_t index = distance(sums.begin(), iter);
            optCost[begin][begin + len] = keySumCost[begin][begin + len] + sums[index];
        }
    }

    return optCost[0][n - 1];
}

int main()
{
    int n;
    cin >> n;
    vector<double> array_k;
    vector<double> array_d;
    for (int i = 0; i < n; i++)
    {
        double num;
        cin >> num;
        array_k.push_back(num);
    }
    for (int i = 0; i < n + 1; i++)
    {
        double num;
        cin >> num;
        array_d.push_back(num);
    }
    vector<vector<double>> keySumCost = setKeySumCost(array_k, array_d);
    double minCost = getMinCost(keySumCost);
    cout << fixed << setprecision(12) << minCost << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 7100
final_rank: 16

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

double solve(const std::vector<double>& p, std::vector<double>& q) {
    std::vector<std::vector<double>> sumMem(q.size(), std::vector<double>(q.size(), 0));
    for (int i = 0; i < sumMem.size(); ++i) {
        sumMem[i][i] = q[i]; 
        for (int j = i + 1; j < sumMem[i].size(); ++j) {
            sumMem[i][j] = sumMem[i][j-1] + p[j-1] + q[j];
        }
    }
    std::vector<std::vector<double>> minCostMem(q.size(), std::vector<double>(q.size(), 0));
    for (int len = 0; len < q.size(); ++len) {
        for (int i = 0; i + len < q.size(); ++i) {
            int k = i + len;
            std::vector<double> c;
            c.reserve(len);
            for (int j = i + 1; j <= k; ++j) {
                c.push_back(minCostMem[i][j-1] + minCostMem[j][k]);
            }
            minCostMem[i][k] = (c.empty() ? 0 : *std::min_element(c.begin(), c.end())) + sumMem[i][k];
        }
    }
    return minCostMem[0][p.size()];
}

int main() {
    int n;
    std::cin >> n;
    std::vector<double> p(n);
    for (double& v : p) {
        std::cin >> v;
    }
    std::vector<double> q(n+1);
    for (double& v : q) {
        std::cin >> v;
    }

    std::cout << solve(p, q) << std::endl;
}
accuracy: 1
time_ms: 30
memory_kb: 7560
final_rank: 11

code_snippet: #include <iostream>
#include <vector>
#include <cmath>

double solve(const std::vector<double>& p, std::vector<double>& q) {
    std::vector<std::vector<double>> sumMem(q.size(), std::vector<double>(q.size(), 0));
    for (int i = 0; i < sumMem.size(); ++i) {
        sumMem[i][i] = q[i]; 
        for (int j = i + 1; j < sumMem[i].size(); ++j) {
            sumMem[i][j] = sumMem[i][j-1] + p[j-1] + q[j];
        }
    }
    std::vector<std::vector<double>> minCostMem(q.size(), std::vector<double>(q.size(), 0));
    for (int len = 0; len < q.size(); ++len) {
        for (int i = 0; i + len < q.size(); ++i) {
            int k = i + len;
            double m = INFINITY;
            for (int j = i + 1; j <= k; ++j) {
                m = std::min(m, minCostMem[i][j-1] + minCostMem[j][k]);
            }
            minCostMem[i][k] = (std::isinf(m) ? 0 : m) + sumMem[i][k];
        }
    }
    return minCostMem[0][p.size()];
}

int main() {
    int n;
    std::cin >> n;
    std::vector<double> p(n);
    for (double& v : p) {
        std::cin >> v;
    }
    std::vector<double> q(n+1);
    for (double& v : q) {
        std::cin >> v;
    }

    std::cout << solve(p, q) << std::endl;
}
accuracy: 1
time_ms: 20
memory_kb: 7092
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;

// 各範囲のキーのコストの合計を求める
vector<vector<double>> setKeySumCost(const vector<double> &array_k, const vector<double> &array_d)
{
    int n = array_k.size() + 1;
    vector<vector<double>> keySumCost(n);
    for (int i = 0; i < n; i++)
    {
        keySumCost[i].resize(n);
        keySumCost[i][i] = array_d[i];
        for (int j = i + 1; j < n; j++)
        {
            keySumCost[i][j] = keySumCost[i][j - 1] + array_k[j - 1] + array_d[j];
        }
    }
    return keySumCost;
}

// 最小のコストを求める
double getMinCost(const vector<vector<double>> &keySumCost)
{
    int n = keySumCost.size();
    vector<vector<double>> optCost(n);
    for (int i = 0; i < n; i++)
    {
        optCost[i].resize(n);
        optCost[i][i] = keySumCost[i][i];
    }
    for (int i = 0; i < n - 1; i++)
    {
        optCost[i][i + 1] = keySumCost[i][i + 1] + optCost[i][i] + optCost[i + 1][i + 1];
    }

    // 範囲の長さを指定
    // 最初は短い範囲から、最後は全体の範囲で最小のコストを求める
    for (int len = 2; len < n; len++)
    {
        // 起点を設定する
        // 最初は 1~2, 2~3
        for (int begin = 0; begin < n - len; begin++)
        {
            // 範囲内でどのキーを中央にすると最小のコストになるか求める
            // 1 , (2) or (1), 2
            vector<double> sums;
            for (int r = begin + 1; r <= begin + len; r++)
            {
                double left = begin + 1 < r ? optCost[begin][r - 1] : optCost[begin][begin];
                double right = r < begin + len ? optCost[r][begin + len] : optCost[begin + len][begin + len];
                sums.push_back(left + right);
            }
            vector<double>::iterator iter = min_element(sums.begin(), sums.end());
            size_t index = distance(sums.begin(), iter);
            optCost[begin][begin + len] = keySumCost[begin][begin + len] + sums[index];
        }
    }

    return optCost[0][n - 1];
}

int main()
{
    int n;
    cin >> n;
    vector<double> array_k;
    vector<double> array_d;
    for (int i = 0; i < n; i++)
    {
        double num;
        cin >> num;
        array_k.push_back(num);
    }
    for (int i = 0; i < n + 1; i++)
    {
        double num;
        cin >> num;
        array_d.push_back(num);
    }
    vector<vector<double>> keySumCost = setKeySumCost(array_k, array_d);
    double minCost = getMinCost(keySumCost);
    cout << fixed << setprecision(12) << minCost << endl;
}
accuracy: 1
time_ms: 60
memory_kb: 7124
final_rank: 17

code_snippet: #include <iostream>
#include <vector>
#include <cmath>

double solve(const std::vector<double>& p, std::vector<double>& q) {
    std::vector<std::vector<double>> minCostMem(q.size(), std::vector<double>(q.size(), 0));
    std::vector<std::vector<double>> sumMem(q.size(), std::vector<double>(q.size(), 0));

    for (int i = 0; i < sumMem.size(); ++i) {
        sumMem[i][i] = q[i]; 
        for (int j = i + 1; j < sumMem[i].size(); ++j) {
            sumMem[i][j] = sumMem[i][j-1] + p[j-1] + q[j];
        }
    }
    for (int len = 0; len < q.size(); ++len) {
        for (int i = 0; i < q.size() - len; ++i) {
            int k = i + len;
            double m = INFINITY;
            for (int j = i + 1; j <= k; ++j) {
                m = std::min(m, minCostMem[i][j-1] + minCostMem[j][k]);
            }
            minCostMem[i][k] = (std::isinf(m) ? 0 : m) + sumMem[i][k];
        }
    }
    return minCostMem[0][p.size()];
}

int main() {
    int n;
    std::cin >> n;
    std::vector<double> p(n);
    for (double& v : p) {
        std::cin >> v;
    }
    std::vector<double> q(n+1);
    for (double& v : q) {
        std::cin >> v;
    }

    std::cout << solve(p, q) << std::endl;
}
accuracy: 1
time_ms: 20
memory_kb: 7108
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
#include <cmath>

double solve(const std::vector<double>& p, std::vector<double>& q) {
    std::vector<std::vector<double>> minCostMem(q.size(), std::vector<double>(q.size(), 0));
    std::vector<std::vector<double>> sumMem(q.size(), std::vector<double>(q.size(), 0));

    for (int i = 0; i < sumMem.size(); ++i) {
        sumMem[i][i] = q[i]; 
        for (int j = i + 1; j < sumMem[i].size(); ++j) {
            sumMem[i][j] = sumMem[i][j-1] + p[j-1] + q[j];
        }
    }

    for (int i = 0; i < q.size(); ++i) {
        minCostMem[i][i] = q[i];
    }
    for (int len = 1; len < q.size(); ++len) {
        for (int i = 0; i < q.size() - len; ++i) {
            int k = i + len;
            double m = INFINITY;
            for (int j = i + 1; j <= k; ++j) {
                m = std::min(m, minCostMem[i][j-1] + minCostMem[j][k]);
            }
            minCostMem[i][k] = m + sumMem[i][k];
        }
    }
    return minCostMem[0][p.size()];
}

int main() {
    int n;
    std::cin >> n;
    std::vector<double> p(n);
    for (double& v : p) {
        std::cin >> v;
    }
    std::vector<double> q(n+1);
    for (double& v : q) {
        std::cin >> v;
    }

    std::cout << solve(p, q) << std::endl;
}
accuracy: 1
time_ms: 20
memory_kb: 7136
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <cmath>

class Solver {
     const std::vector<double> p;
     const std::vector<double> q;
     std::vector<std::vector<double>> minCostMem;
     std::vector<std::vector<double>> sumMem;

public:
    Solver(const std::vector<double>& p, std::vector<double>& q) : p(p), q(q)
    {
        minCostMem = std::vector<std::vector<double>>(q.size(), std::vector<double>(q.size(), 0));
        sumMem = std::vector<std::vector<double>>(q.size(), std::vector<double>(q.size(), 0));

        for (int i = 0; i < sumMem.size(); ++i) {
            sumMem[i][i] = q[i]; 
            for (int j = i + 1; j < sumMem[i].size(); ++j) {
                sumMem[i][j] = sumMem[i][j-1] + p[j-1] + q[j];
            }
        }

        for (int i = 0; i < q.size(); ++i) {
            minCostMem[i][i] = q[i];
        }
        for (int len = 1; len < q.size(); ++len) {
            for (int i = 0; i < q.size() - len; ++i) {
                int k = i + len;
                double m = INFINITY;
                for (int j = i + 1; j <= k; ++j) {
                    m = std::min(m, minCostMem[i][j-1] + minCostMem[j][k] + sumMem[i][k]);
                }
                minCostMem[i][k] = m;
            }
        }

    }
    double minCost(int i, int k) {
        return minCostMem[i][k];
    }
};

int main() {
    int n;
    std::cin >> n;
    std::vector<double> p(n);
    for (double& v : p) {
        std::cin >> v;
    }
    std::vector<double> q(n+1);
    for (double& v : q) {
        std::cin >> v;
    }

    Solver solver(p, q);
    std::cout << solver.minCost(0,n) << std::endl;
}
accuracy: 1
time_ms: 20
memory_kb: 7492
final_rank: 8

code_snippet: #include <iostream>
#include <vector>
#include <cmath>

class Solver {
     const std::vector<double> p;
     const std::vector<double> q;
     std::vector<std::vector<double>> minCostMem;
     std::vector<std::vector<double>> sumMem;

    double sum(int i, int k) {
        return sumMem[i][k];
    }
public:
    Solver(const std::vector<double>& p, std::vector<double>& q) : p(p), q(q)
    {
        minCostMem = std::vector<std::vector<double>>(q.size(), std::vector<double>(q.size(), 0));
        sumMem = std::vector<std::vector<double>>(q.size(), std::vector<double>(q.size(), 0));

        for (int i = 0; i < sumMem.size(); ++i) {
            sumMem[i][i] = q[i]; 
            for (int j = i + 1; j < sumMem[i].size(); ++j) {
                sumMem[i][j] = sumMem[i][j-1] + p[j-1] + q[j];
            }
        }
    }
    double minCost(int i, int k) {
        if (minCostMem[i][k]) return minCostMem[i][k];
        if (i == k) return q[i];
        double m = INFINITY;
        for (int j = i + 1; j <= k; ++j) {
            m = std::min(m, minCost(i, j-1) + minCost(j, k) + sum(i, k));
        }
        minCostMem[i][k] = m;
        return m;
    }
};

int main() {
    int n;
    std::cin >> n;
    std::vector<double> p(n);
    for (double& v : p) {
        std::cin >> v;
    }
    std::vector<double> q(n+1);
    for (double& v : q) {
        std::cin >> v;
    }

    Solver solver(p, q);
    std::cout << solver.minCost(0,n) << std::endl;
}
accuracy: 1
time_ms: 110
memory_kb: 7580
final_rank: 19