题目
错解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 310;
int a[N], s[N], f[N][N];
int main()
{
int n;
cin >> n;
memset(f, 0x3f, sizeof f);
for(int i = 1; i <= n; i++)
{
cin >> a[i];
s[i] = s[i-1] + a[i];
f[i][i] = 0;
}
for(int i = 1; i < n; i++)
{
for(int j = i+1; j <= n; j++)
{
for(int k = i; k < j; k++)
{
f[i][j] = min(f[i][j], f[i][k] + f[k+1][j] + s[j] - s[i-1]);
}
}
}
cout << f[1][n];
}
分析
应该从小区间遍历到大区间。因为这个更新方向是从小到大(先整合一小部分,再整合大部分),而不是从左到右、从上往下。
正解
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 310;
int a[N], s[N], f[N][N];
int main()
{
int n;
cin >> n;
memset(f, 0x3f, sizeof f);
for(int i = 1; i <= n; i++)
{
cin >> a[i];
s[i] = s[i-1] + a[i];
f[i][i] = 0;
}
for(int len = 2; len <= n; len++)
{
for(int i = 1; i + len -1 <= n; i++)
{
int j = i + len - 1;
for(int k = i; k < j; k++)
{
f[i][j] = min(f[i][j], f[i][k] + f[k+1][j] + s[j] - s[i-1]);
}
}
}
cout << f[1][n];
return 0;
}