题意分析
区间dp
状态设计
dp[i][j]表示从第i堆石子到第j堆石子的最小花费。
状态转移
dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+sum[i][j]) d p [ i ] [ j ] = m a x ( d p [ i ] [ j ] , d p [ i ] [ k ] + d p [ k + 1 ] [ j ] + s u m [ i ] [ j ] ) 。
其中 sum[i][j]=∑jk=ia[k] s u m [ i ] [ j ] = ∑ k = i j a [ k ] 。即第i堆到第j堆石子求和。
详情请见代码
代码总览
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int nmax = 105;
const int INF = 0x3f3f3f3f;
int a[nmax];
int sum[nmax][nmax];
int dp[nmax][nmax];
int n;
int main(){
while(scanf("%d",&n)!=EOF){
memset(a,0,sizeof a);
memset(sum,0,sizeof sum);
memset(dp,0,sizeof dp);
for(int i = 1 ;i<=n;++i) {
scanf("%d",&a[i]);
sum[i][i] = a[i];
}
for(int i = 1;i<=n;++i)
for(int j=i+1;j<=n;++j)
sum[i][j] = sum[i][j-1] + a[j];
for(int len = 2;len<=n;++len){
for(int i = 1;i<=n-len+1;++i){
int j = i+len-1;
dp[i][j] = INF;
for(int k = i;k<=j-1;++k){
dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j] + sum[i][j]);
}
}
}
printf("%d\n",dp[1][n]);
}
return 0;
}