ATC DP N Slimes
https://atcoder.jp/contests/dp/tasks/dp_n
就采取区间更新的策略就好了,先枚举大区间然后枚举区间的中断点,选取最合适的中断点即可。
d p [ s t ] [ l e n ] = m i n ( d p [ s t ] [ l e n ] , d p [ s t ] [ c u t − s t + 1 ] + d p [ c u t + 1 ] [ e d − c u t ] ) ; dp[st][len] = min(dp[st][len], dp[st][cut - st + 1]+dp[cut+1][ed-cut]); dp[st][len]=min(dp[st][len],dp[st][cut−st+1]+dp[cut+1][ed−cut]);
#include <iostream>
#include <cstdio>
using namespace std;
const int N = 1e3 + 100;
typedef long long ll;
ll num[N];
ll dp[N][N];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> num[i];
dp[i][1] = num[i];
num[i] += num[i - 1];
}
for (int len = 2; len <= n; len++) {
for (int st = 1; st <= n + 1 - len; st++) {
int ed = st + len - 1;
dp[st][len] = 1LL << 50;
for (int cut = st; cut < ed; cut++) {
ll l_sum = dp[st][cut - st + 1];
ll r_sum = dp[cut + 1][ed - cut];
dp[st][len] = min(dp[st][len], l_sum + r_sum);
}
ll sum = num[ed] - num[st - 1];
dp[st][len] += sum;
}
}
cout << dp[1][n] - num[n] << endl;
}