南邮 OJ 1038 最小代价树

最小代价树

时间限制(普通/Java) :  1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 388            测试通过 : 98 

比赛描述

以下方法称为最小代价的字母树:给定一正整数序列,例如:4123,在不改变数的位置的条件下把它们相加,并且用括号来标记每一次加法所得到的和。
例如:((4+12+3))=((5+5))=10。除去原数不4123之外,其余都为中间结果,如5510,将中间结果相加,得到: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

题目来源

OIBH 模拟赛


#include <stdio.h>
#define MAX_N 200
#define LARGE 100000000
#define MIN(a,b) (a<b?a:b)
int main(void){
	unsigned short N=0,i=0,j=0,k=0,l=0;
	unsigned long g[MAX_N][MAX_N]={0};
	unsigned long f[MAX_N][MAX_N]={0};	
	scanf("%hu",&N);
	for(i=0;i<N;++i)
		scanf("%ld",&g[i][i]);
	for(i=0;i<N;++i)
		for(j=i+1;j<N;++j)
			g[i][j] = g[i][j-1]+g[j][j];
	for(i=0;i<N;++i)
		f[i][i] = 0;	
	for(l=1;l<N;++l){
		for(i=0;i<N-l;++i){
			j = i+l;
			f[i][j] = LARGE;
			for(k=i;k<=j-1;++k){
				f[i][j] = MIN(f[i][j],f[i][k]+f[k+1][j]);
			}
			f[i][j] += g[i][j]; 
		}
	}
	printf("%ld\n",f[0][N-1]);
	return 0;
}





你可能感兴趣的:(ACM,南邮OJ,最小代价树)