for (int i = 1; i <= n; i ++) cin >> s[i]; //读入数组 for (int i = 1; i <= n; i ++) s[i] += s[i - 1]; //求其前缀和
for (int len = 2; len <= n; len ++) //枚举长度 for (int i = 1; i + len - 1 <= n; i ++) //从前到后,枚举不同长度下,给左边区域和右边区域分配不同数量是的代价,求最小值 { int l = i, r = i + len - 1; //以当前位置为左边部分(只有一个数),剩余部分都是右边部分 f[l][r] = 1e8; //先将所有从第l堆石子到第r堆石子合并到一堆石子的代价置为无穷 for (int k = l; k < r; k ++) //逐渐将右边的数拿给左边求代价,右边至少留一个 f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r] + s[r] - s[l - 1]); }
for (int len = 1; len <= n; len++) { // 区间长度 for (int i = 1; i + len - 1 <= n; i++) { // 枚举起点 int j = i + len - 1; // 区间终点 if (len == 1) { dp[i][j] = 初始值 continue; }
for (int k = i; k < j; k++) { // 枚举分割点,构造状态转移方程 dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + w[i][j]); } } }