区間 を合成するために必要なスタミナの最小値
という動的計画法を考えます。
区間の範囲 を広げながら遷移を行うことで正しく計算することができます。(詳しくは実装例を参照してください。)
あらかじめ累積和を計算しておくことによって、動的計画法を計算を で計算することができます。
あとは、区間の和が 以上になっている区間においての DP テーブルの最小値を出力すればよいです。
#include<bits/stdc++.h>
using namespace std;
const long long INF = 0x1fffffffffffffff;
int main(){
long long n, k;
cin >> n >> k;
vector<long long> a(n);
for(int i = 0; i < n; i++){
cin >> a[i];
}
vector<vector<long long>> dp(n, vector<long long>(n, 0));
for(int i = 0; i < n; i++){
for(int j = i + 1; j < n; j++){
dp[i][j] = INF;
}
}
vector<long long> sum(n + 1);
for(int i = 0; i < n; i++){
sum[i + 1] = sum[i] + a[i];
}
for(int d = 1; d < n; d++){
for(int i = 0; i < n; i++){
int l = i, r = l + d;
if(r >= n) continue;
for(int j = l + 1; j <= r; j++){
dp[l][r] = min(dp[l][r], dp[l][j - 1] + dp[j][r] + abs((sum[j] - sum[l] - sum[r + 1] + sum[j])));
}
}
}
long long ans = INF;
for(int i = 0; i < n; i++){
for(int j = i; j < n; j++){
if(sum[j + 1] - sum[i] >= k){
ans = min(ans, dp[i][j]);
}
}
}
if(ans == INF){
cout << -1 << endl;
}else{
cout << ans << endl;
}
}