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;

}

你可能感兴趣的:(dp)