累加器传送门:
http://blog.csdn.net/NOIAu/article/details/71775000
题目传送门:
https://cn.vjudge.net/problem/HDU-2829
这道题我在这篇博客上写过斜率优化的题解:
http://blog.csdn.net/NOIAu/article/details/72369084
这里我就不对dp转移进行讲解,由于cost满足凸性和包含关系,直接四边形即可,如果需要看详解(其实一点都不详),可以看上面那篇博客
代码如下
#include<cstdio>
#include<iostream>
#include<cstring>
#define MAXN 1000+10
using namespace std;
int dp[MAXN][MAXN],s[MAXN][MAXN];
int a[MAXN],cost[MAXN][MAXN],cnt[MAXN];
int n,m;
bool init(){
scanf("%d%d",&n,&m);
if(n==0&&m==0) return false;
for(register int i=1;i<=n;i++)scanf("%d",&a[i]);
for(register int i=1;i<=n;i++)cnt[i]=cnt[i-1]+a[i];
for(register int i=1;i<=n;i++)
for(register int j=i+1;j<=n;j++)
cost[i][j]=cost[i][j-1]+(cnt[j-1]-cnt[i-1])*a[j];
return true;
}
void dpp(){
for(register int i=1;i<=n;++i){
dp[1][i]=cost[1][i];
s[1][i]=0;
}
for(register int i=2;i<=m+1;i++){
s[i][n+1]=n;
for(register int j=n;j>i;j--){
int temp=0x7fffffff;
int te;
for(register int k=s[i-1][j];k<=s[i][j+1];k++){
if(temp>dp[i-1][k]+cost[k+1][j]){
temp=dp[i-1][k]+cost[k+1][j];
te=k;
}
}
dp[i][j]=temp;
s[i][j]=te;
}
}
cout<<dp[m+1][n]<<endl;
}
int main(){
while(init()){
dpp();
}
}