NYOJ 737 合并石子(一)

石子合并(一)

时间限制:1000 ms  |  内存限制:65535 KB

难度:3

描述
    有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。

输入
有多组测试数据,输入到文件结束。

每组测试数据第一行有一个整数n,表示有n堆石子。

接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开

输出
输出总代价的最小值,占单独的一行
样例输入
3
1 2 3
7
13 7 8 16 21 4 18
样例输出
9
239

AC码:

#include<stdio.h>
#include<string.h>
#define INF 2000000005
int dp[203][203],sum[203]={0};
int DP(int left,int right)
{
	if(dp[left][right]>=0)  // 某一个区间左端到右端已经得到最优方案
		return dp[left][right];
	if(left==right)         // 说明该区间就一堆石子
	{
		return dp[left][right]=0;
	}
	int min,mid;
	for(mid=left;mid<right;mid++)
	{
		if(dp[left][right]<0)
			dp[left][right]=INF;
		// 核心:动态转移方程
		min=DP(left,mid)+DP(mid+1,right)+(sum[mid]-sum[left-1])+(sum[right]-sum[mid]);
		if(min<dp[left][right])
			dp[left][right]=min;
	}
	return dp[left][right];
}
int main()
{
	int n,i,a;
	while(~scanf("%d",&n))
	{// n表示石子的堆数
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a);
			// a依次表示第i堆的石子数
			sum[i]=a+sum[i-1];
		}
		memset(dp,-1,sizeof(dp));
		printf("%d\n",DP(1,n));
	}
	return 0;
}

区间DP问题!

#include<stdio.h>
#define INF 2000000005
int dp[205][203],sum[203];
int min(int a,int b)
{
	return a>b?b:a;
}
int main()
{
	int n,a;
	while(~scanf("%d",&n))
	{
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a);
			sum[i]=sum[i-1]+a;
			dp[i][i]=0;
		}
		// 区间DP
		for(int count=2;count<=n;count++)
		{   // 遍历合并count=2堆、3堆、...n堆的情况
			for(int start=1;start<=n-count+1;start++)
			{   // start表示每个区间的始点
				int end=start+count-1;  // end表示对应的该区间的终点
				dp[start][end]=INF;
				for(int mid=start;mid<=end;mid++)
				{
					dp[start][end]=min(dp[start][end],dp[start][mid]+dp[mid+1][end]+sum[end]-sum[start-1]);
				}
			}
		}
		printf("%d\n",dp[1][n]);
	}
	return 0;
}

NYOJ 737 合并石子(一)

时间: 2024-10-14 17:48:57

NYOJ 737 合并石子(一)的相关文章

NYOJ 737 石子合并(一) (区间DP+平行四边形优化)

题目地址:NYOJ 737 定义状态dp [ i ] [ j ]为从第i个石子到第j个石子的合并最小代价. 没有优化的代码如下:耗时248ms. #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include

NYOJ 737 石子合并(一)

分析: 本题为区间型动态规划,dp[i][j] 表示从第 i 堆合并到第 j 堆的最小代价, sum[i][i] 表示第 i 堆到第 j 堆的石子总和,则动态转移方程: dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + sum[i][j])  (i <= k <= j - 1). 代码如下: 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm&

合并石子 区间dp水题

合并石子 链接: nyoj 737 描述: 有N堆石子排成一排,每堆石子有一定的数量.现要将N堆石子并成为一堆.合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆.求出总的代价最小值. tags:最基本的区间dp,这题范围小,如果n大一些,还是要加个平行四边行优化. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring&g

NYOJ 832 合并游戏

合并游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 大家都知道Yougth除了热爱编程之外,他还有一个爱好就是喜欢玩.某天在河边玩耍的时候,他发现了一种神奇的石子,当把两个石子放在一起的时候,后一个石子会消失,而且会蹦出一定数量的金币,这可乐坏了Yougth,但是他想得到最多的金币,他该怎么做? 输入 首先一行,一个n(1<=n<=10),表示有n个石子.接下来n*n的一个矩阵,Aij表示第i个和第j个合并蹦出的金币值(小于10000,注意合并后j会消失).

合并石子大总结

合并石子大总结 石子合并问题是最经典的DP问题.首先它有如下3种题型: 一.非相邻两堆石子合并 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为新合成的一堆石子的数量.求将这N堆石子合并成一堆的总花费最小(或最大). 分析:当然这种情况是最简单的情况,合并的是任意两堆,直接贪心即可,每次选择最小的两堆合并.本问题实际上就是哈夫曼的变形. 二.直线型相邻两堆石子合并 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动相邻的2堆石子合并,合并花

环形合并石子

[题目描述] 在一个圆形操场的四周摆放N堆石子(N≤100),现要将石子有次序地合并成一堆.规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.编一程序,读入堆数N及每堆石子数(≤100)选择一种合并石子的方案,分别得到合并这N堆石子为一堆,可以得到的最大得分和最小得分 [输入描述] 输入包含多个例子.第一行为N,即石子堆的数目,以下一行为N个整形,分别代表每堆石子的数目.当N=0时,输入结束. [输出描述] 对每个例子,输出其最小得分和最大得分,这两个数值以空格间

合并类动态规划,石子归并,合并石子解题报告

石子归并问题 1:任意版 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为将的一堆石子的数量.设计一个算法,将这N堆石子合并成一堆的总花费最小(或最大). 此类问题比较简单,就是哈夫曼编码的变形,用贪心算法即可求得最优解.即每次选两堆最少的,合并成新的一堆,直到只剩一堆为止.证明过程可以参考哈夫曼的证明过程. 2.链式归并 问题描述 设有N堆沙子排成一排,其编号为1,2,3,-,N(N<=100).每堆沙子有一定的数量.现要将N堆沙子并成为一堆.归并的

合并石子 四边形不等式优化

题目描述 有一排石子,共n 堆.现要将石子有次序地合并成一堆.规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.试设计一个算法,计算出将n堆石子合并成一堆的最小得分. 题解 首先由直接动态规划的方法来做,即 for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) for(int k=i;k<=j;k++) { f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+cost[j]-cost[i-1]);

蒟蒻吃药计划-治疗系列 #round 2 合并石子+乘积最大

1.合并石子 <信息学奥赛一本通>第五版 P371 第三节 T1 我就直接开始讲吧: Warning:这个题目和 合并果子 不一样!不一样!不一样!不一样!不一样!不一样!不一样!不一样! :我想告诉你一个事情,你帮帮我好么? (内心:mmp怎么又是这个人) :昨天我去商场的时候,钱包被偷了,银行卡啥的都没了,你能帮帮我么? (内心:凭啥,我就不帮) :如果你帮我找到的话,我给你50金币好不好? (*听到这句话,你充满了决心) 好吧,那我们帮帮他吧,让我们先看看他遇到了什么问题 :那个小偷在我