最小代价树(0404)
问题描述
以下方法称为最小代价的字母树:给定一正整数序列,例如:4,1,2,3,在不改变数的位置的条件下把它们相加,并且用括号来标记每一次加法所得到的和。
例如:((4+1)+ (2+3))=((5)+(5))=10。除去原数不4,1,2,3之外,其余都为中间结果,如5,5,10,将中间结果相加,得到:5+5+10= 20,那么数20称为此数列的一个代价,若得到另一种算法:(4+((1+2)+3))=(4+((3)+3))=(4+(6))=10,数列的另一个代价为:3+6+10=19。若给出N个数,可加N-1对括号,求出此数列的最小代价。
注:结果范围不超出longint.
输入
第一行为数N(1≤N≤200),第二行为N个正整数,整数之间用空格隔开。
输出
输出仅一行,即为最少代价值。
样例输入
4
4 1 2 3
样例输出
19
简单区间DP、
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
#define ll long long
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define N 310 int a[N];
int sum[N];
int dp[N][N]; //dp[i][j]表示区间i,j的最小代价 int main()
{
int n;
int i,j,k,len;
while(scanf("%d",&n)!=EOF)
{
memset(dp,INF,sizeof(dp));
for(i=;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-]+a[i];
dp[i][i]=;
}
for(len=;len<=n;len++){
for(i=;i<=n-len+;i++){
j=i+len-;
for(k=i;k<j;k++){
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+][j]+sum[j]-sum[i-]);
}
}
}
printf("%d\n",dp[][n]);
}
return ;
}