zafu 1461 (DP)

http://info.zjfc.edu.cn/acm/problemDetail.aspx?pid=1461

 

Simple Game

时间限制 : 1000 ms    内存限制 : 32 MB

提交次数 : 63    通过次数 : 31

题目描述

    有n堆沙子,第i堆沙子的重量是W(i),有一个小游戏是要把这n堆沙子给合并成一堆沙子。
每次只能将相邻两堆沙子合并为一堆沙子,合并两堆沙子为一堆沙子的体能消耗为两堆沙子的重量之和
。聪明的你能不能告诉我,把n堆沙子给合并成一堆沙子,最少需要消费多少体力呢。    举个例子:   
 假设有4堆沙子,重量分别为1、2、3、4,第一次合并两堆沙子的时候,可以合并重量为1、2或者
重量为2、3或者重量为3、4的两堆沙子,因为这些堆沙子是相邻的。假设第一次合并的是第2、3堆
沙子(消费体力2+3=5),那么第一次合并后3堆沙子的重量序列为1、5、4。第二次合并两堆沙子的时候
,可以合并重量为1、5的两堆沙子或者重量为5、4的两堆沙子,因为它们是相邻的。假设第二次合并的是
后面两堆沙子(消费体力5+4=9),则合并后剩余2堆的沙子的重量序列为1、9。最后将剩余两堆沙子合
并(消费体力1+9=10)。这个过程中共消费体力5+9+10=24。    以上例子只是说明合并沙堆的过程中,
并不是最优方案。

输入描述

    本题包含多组测试数据,在每组测试数据中:第一行包含一个正整数n(小于等于100),
    接下来是第二行是n个整数表示n堆沙子的重量(小于等于100)。

输出描述

    对于每组数据,输出一个数,表示将输入n堆石子合并为一堆石子消费的最少体力。

样例输入

3
6 7 8
3
6 8 7

样例输出

34
35

作者

Xie Wenxiu

来源

浙江农林大学第十届电脑节程序设计大赛正式赛

 

 

/*
	校赛时用贪心写WA,想到DP,但不会转移方程,DP该练了

	dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j])+sum[i][j];	
	
	考虑问题可以按递归着推,之后反向写方程就行了
*/
#include <stdio.h>
#define MAX 999999999
int dp[105][105];
int sum[105][105];
int min(int a,int b)
{
	return a<b?a:b;
}
int main()
{
	int i,j,k,n;
	int a[105];
	while(scanf("%d",&n)!=EOF)
	{
		sum[1][0]=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			sum[1][i]=sum[1][i-1]+a[i];
		}
		//
		for(i=1;i<=n;i++)
		{
			for(j=1;j<=n;j++)
			{
				dp[i][j]=MAX;
			}
			dp[i][i]=0;
		}
		for(i=2;i<=n;i++)
		{
			sum[i][i]=a[i];
			for(j=i+1;j<=n;j++)
			{
				sum[i][j]=sum[1][j]-sum[1][i-1];
			}
		}
		//关键代码
		for(i=n;i>=1;i--)
		{
			for(k=i;k<=n;k++)	
			{
				for(j=k+1;j<=n;j++)
				{
					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;
}
posted @ 2010-11-30 22:24  kfinder  阅读(332)  评论(0)    收藏  举报