建树的时候发现是一道区间dp。
这题没有卡时间,给了三秒,测评机速度还算很快。
264914 | 压缩编码 | 01-06 13:28 | 522B | C++ | 正确 | 100 | 1.812s | 4.898MB |
264913 | 压缩编码 | 01-06 13:15 | 691B | C++ | 正确 | 100 | 46ms | 8.730MB |
不加优化:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,a[1001],dp[1001][1001];
int main()
{
memset(dp,0x3f,sizeof dp);
scanf("%d",&n);
for (int i=1;i<=n;++i) {
scanf("%d",&a[i]);
dp[i][i]=0;
a[i]+=a[i-1];
}
for (int l=1;l<n;++l)
for (int i=1;i<=n-l;++i) {
int j=i+l;
for (int k=i;k<j;++k)
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+a[j]-a[i-1]);
}
printf("%d\n",dp[1][n]);
return 0;
}
四边形不等式优化:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,a[1001],dp[1001][1001],s[1001][1001];
int main()
{
memset(dp,0x3f,sizeof dp);
scanf("%d",&n);
for (int i=1;i<=n;++i) {
scanf("%d",&a[i]);
dp[i][i]=0;
s[i][i]=i;
a[i]+=a[i-1];
}
for (int l=1;l<n;++l)
for (int i=1;i<=n-l;++i) {
int j=i+l;
for (int k=s[i][j-1];k<=s[i+1][j];++k) {
if (dp[i][k]+dp[k+1][j]+a[j]-a[i-1]<dp[i][j]) {
dp[i][j]=dp[i][k]+dp[k+1][j]+a[j]-a[i-1];
s[i][j]=k;
}
}
}
printf("%d\n",dp[1][n]);
return 0;
}