动态规划

动态规划之石子合并问题

霸气de小男生 提交于 2019-12-02 20:41:40
#include <iostream> using namespace std; #define LEN 1024 #define MAXDATA 200000 int MIN[LEN][LEN];//最小得分 int MAX[LEN][LEN];//最大得分 int data[LEN];//初始每堆石子数 int sum[LEN];//0-LEN石子堆数 int min(int a, int b) { return a > b? b : a; } int max(int a, int b) { return a > b ? a : b; } void straight(int len) { //初始化对角线 for (int i = 1; i <= len; ++i) { MIN[i][i] = 0; MAX[i][i] = 0; } sum[0] = 0; sum[1] = data[1]; for (int i = 1; i < len; ++i) { sum[i + 1] = sum[i] + data[i + 1]; } for (int i = 0; i <= len; ++i) { std::cout << sum[i] << "\t"; } //数据坐标分析 for (int v = 2; v <= len; ++v) { for (int i = 1; i <=

【动态规划】石子合并 (ssl 2863)

拜拜、爱过 提交于 2019-12-02 20:41:02
石 子 合 并 石子合并 石 子 合 并 Description 在一个操场上一排地摆放着N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请设计一个程序,计算出将N堆石子合并成一堆的最小得分。 Input 每组数据第1行为一个正整数N(2<=N<=100),以下N行,每行一个正整数,小于10000,分别表示第i堆石子的个数(1<=i<=N)。 Output 对于每组数据输出一个正整数,即最小得分 Sample Input 7 13 7 8 16 21 4 18 Sample Output 239 说明: 本题之前用两个方法做过,这次用三个方法做 方 法 一 方法一 方 法 一 先枚举前面的数(i),再枚举后面的数(j),最后枚举中间的分割线(c) (三重循环) 用i到c-1之间的数加上c到j的数再加上之前的得分,再将所有的值去最小。(计算一个数到另一个数可以用前缀和搞定) 状态转移方程: f [ i ] [ j ] = m i n ( f [ i ] [ j ] , f [ i ] [ c − 1 ] + f [ c ] [ j ] + s [ j ] − s [ i − 1 ] ) f[i][j]=min(f[i][j],f[i][c-1]+f[c][j]+s[j]-s[i-1]) f [ i ] [ j

动态规划之石子合并

混江龙づ霸主 提交于 2019-12-02 20:40:45
石子游戏有两种:一种是博弈方面;另一种是合并规划方面的。前者需要太厉害的判断,而且要用到很多数学方面的结论,所以俺不会。这里主要探讨一下石子归并方面的问题与算法。 一 . 简单的石子合并 问题类似于背包问题:给出 n 堆石子的数量,请你求出:由这 n 堆石子可以合并得到的所有重量;或求出合并成两堆之后的最小质量差是多少。 其实上一篇谈到的“数字 N 能否表示成若干个不相同的阶乘的和”就是这个问题的前半部分,前面是采用搜索得到所有可以组成的数量,本文下面采用动态规划来求得所有可以组成的数量。然后再解决该问题的后半部分。 (1) 问题前半部分 动态规划:首先是定义好状态,这个问题是求所有可以合并后的和,那么我们就可以利用标号的方法来标记所有可以合并得到的和。数组 num[n] 表示读入的 n 堆石子数量。利用 bool 数组 f[N] , (N 为这 n 堆石子的重量之和 ) ,状态 f[i] = true 表示可以得到和为 i ,否则 =false ,表示不可以得到和为 i ,有: 边界条件 f[0] = true ---- 尽管没实际意义,但对于 DP 来说却是必需的 f[i+num[j]] = f[i+num[j]] | f[i]; ---- i 满足的条件是: 0 <= i <= total – num[j] 。方程的意思就是:总数为 i 的状态可以加上 j 组成总合为 i+j

动态规划专题之合并石子

一世执手 提交于 2019-12-02 20:40:31
/* Name: 动态规划专题之合并石子 Author: 巧若拙 Description: 在一个操场上摆放着一排N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。 试设计一个算法,计算出将N堆石子合并成一堆的最小得分。 输入描述 Input Description 第一行是一个数N。1≤N≤100 以下N行每行一个数A,表示石子数目。1≤A≤200 输出描述 Output Description 共一个数,即N堆石子合并成一堆的最小得分。 样例输入 Sample Input 7 13 7 8 16 21 4 18 样例输出 Sample Output 239 */ #include<iostream> using namespace std; const int INT_MAX = 2147483647; const int MAX = 1000; int A[MAX+1];//记录每堆石子的数量 int Sum[MAX+1];//记录前n堆石子的数量 int B[MAX+1][MAX+1];//记录第i个矩阵至第j个矩阵的最优解 int S[MAX+1][MAX+1];//记录从哪里断开的才可得到矩阵的最优解 bool flag[MAX+1]; //记录A[i]是否已经被输出过 int

【动态规划】石子合并

杀马特。学长 韩版系。学妹 提交于 2019-12-02 20:39:58
石 子 合 并 石子合并 石 子 合 并 Description 在一个操场上一排地摆放着N堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。请设计一个程序,计算出将N堆石子合并成一堆的最小得分。 Input 每组数据第1行为一个正整数N(2<=N<=100),以下N行,每行一个正整数,小于10000,分别表示第i堆石子的个数(1<=i<=N)。 Output 对于每组数据输出一个正整数,即最小得分 Sample Input 7 13 7 8 16 21 4 18 Sample Output 239 解题方法: 这道题我们可以用两个方法来做,两种方法分别如下: 方法1:先枚举边界,再枚举中间的断点,将断点两边的分值加在一起,再加上当前的分值 # include <iostream> using namespace std ; int main ( ) { int a [ 100 ] , f [ 100 ] [ 100 ] , n , o ; cin >> n ; for ( int i = 1 ; i <= n ; i ++ ) { cin >> o ; a [ i ] = a [ i - 1 ] + o ; //求前缀和 } memset ( f , 127 / 3 , sizeof ( f ) ) ; for

动态规划经典——石子归并

ⅰ亾dé卋堺 提交于 2019-12-02 20:36:57
1.链式归并 问题描述 设有N堆沙子排成一排,其编号为1,2,3,…,N(N<=100)。每堆沙子有一定的数量。现要将N堆沙子并成为一堆。归并的过程只能每次将相邻的两堆沙子堆成一堆,这样经过N-1次归并后成为一堆。找出一种合理的归并方法,使总的代价最小。 【输入格式】 输入由若干行组成,第一行有一个整数,n(1≤n≤ 10 0);表示沙子堆数。第2至m+1行是每堆沙子的数量。 【输出格式】 一个整数,归并的最小代价。 【输入样例】 输入文件名: shizi.in 7 13 7 8 16 21 4 18 【输出样例】 输出文件名: shizi.out 239 令f[i,j]表示归并第i个数到第j数的最小代价,sum[i,j]表示第i个数到第j个数的和,这个可以事先计算出来。sum[i,j]可以在O(1)的时间内算出. 容易的到以下的动态转移方程: 阶段:以归并石子的长度为阶段,一共有n-1个阶段。 状态:每个阶段有多少堆石子要归并,当归并长度为2时,有n-1个状态; 当归并长度为3时,有n-2个状态; 当归并长度为n时,有1个状态。 决策:当归并长度为2时,有1个决策;当归并长度为3时,有2个决策; 当归并长度为n时,有n-1个决策。 #include <iostream> using namespace std; #define M 101 #define INF

石子合并问题(动态规划)

假如想象 提交于 2019-12-02 20:35:26
一条直线上摆放着一行共n堆的石子。现要将石子有序地合并成一堆。规定每次只能选相邻的两堆合并成新的一堆,并将新的一堆石子数记为该次合并的得分。 请编辑计算出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。 Input 输入有多组测试数据。 每组第一行为n(n<=100),表示有n堆石子,。 二行为n个用空格隔开的整数,依次表示这n堆石子的石子数量ai(0<ai<=100) Output 每组测试数据输出有一行。输出将n堆石子合并成一堆的最小得分和将n堆石子合并成一堆的最大得分。 中间用空格分开。 间用空格分开。 Sample Input 3 1 2 3 Sample Output 9 11 1 #include<iostream> 2 #include <cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define INF 0x3f3f3f3f 7 8 int dp[ 105 ][ 105 ]; 9 int sum[ 110 ]; 10 int ans= 0 ,cnt= 0 ; 11 12 int dfs( int l, int r){ /* 求最大 */ 13 if (dp[l][r]!=- 1 ){ 14 return dp[l][r]; 15 } 16 if

动态规划之石子合并三(Java 版本)

六月ゝ 毕业季﹏ 提交于 2019-12-02 20:30:37
题目描述 有N堆石子围成 一个圆 ,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。 输入 有 多组 测试数据,输入到文件结束。 每组测试数据第一行有一个整数n,表示有n堆石子。 接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开。 输出 输出总代价的最小值,占单独的一行。 样例输入 3 1 2 3 4 3 5 2 3 6 3 5 7 3 4 2 样例输出 9 26 60 题目解析: 这道题目是直线形石子合并的拓展题——环形石子的合并,那么我们思考,是否可以 划圆为直 呢?我们可以把圆形剪开,假设石子堆为1,2,3,那么剪开的直线形石子堆为1,2,3,1,2,我们假设原来的数组长度为n,那么现在剪开的直线形石子堆数组长度为 2*n-1 ,我们相对于之前的做法,只需要 多一层判断,即依次判断0——n-1,1——n,.......,n-1——2*n-2区间石子堆的代价最小值即可(这里的区间用数组的下标进行表示) 。 参考代码: import java.util.Scanner; /** * 环型石子合并(递归求解) * @author autumn_leaf * @Date 2019/03/22 */ public class

算法第三章作业

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-02 20:26:45
1. 你对动态规划算法的理解(2分)   动态规划算法其实与分治法有相通性,都是将待解决的问题分解成若干子问题,先求子问题,再结合这些子问题的解得到原问题的解。不过,不同之处在于,适用动态规划算法的问题,经分解后得到的子问题往往不是相对独立的。用分治法来解决问题,往往有些子问题会被重复计算了许多次。而动态规划算法的基本思想就是不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中,这样便可以避免大量的重复计算,从而得到多项式时间算法。   动态规划的基本步骤为:1、找出最优解的性质,并刻画其结构特征;2、递归地定义最优值;3、以自底向上的方式计算最优值;4、根据计算最优值时得到的信息,构造最优解。   不过有时最好也可以避免递归,其步骤为:1、确定表的维数;2、确定填表范围;3、确定按什么顺序填表(自左向右/自下而上)。 2. 分别列出编程题1、2的递归方程(2分) 3. 说明结对编程情况(1分)   结对编程可以及时进行更好的想法的提出与补充,也能帮助自己更好的理解算法的原理,明白其计算过程。我们通常是在周一毛概课、周三笔译课下课后,利用吃饭前的一段时间进行讨论和编程答题。 来源: https://www.cnblogs.com/wen-05/p/11762590.html

石子合并(动态规划DP)

时间秒杀一切 提交于 2019-12-02 20:22:35
时限: 1000ms 内存限制:10000K 总时限:3000ms 描述: 在一个圆形操场的四周摆放着n堆石子(n<= 100),现要将石子有次序地合并成一堆。规定每次只能选取相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 编一程序,读入石子堆数n及每堆的石子数(<=20)。选择一种合并石子的方案,使得做n-1次合并,得分的总和最小; 比如有4堆石子:4 4 5 9 则最佳合并方案如下: 4 4 5 9 score: 0 8 5 9 score: 8 13 9 score: 8 + 13 = 21 22 score: 8 + 13 + 22 = 43 输入: 可能有多组测试数据。 当输入n=0时结束! 第一行为石子堆数n(1<=n<=100);第二行为n堆的石子每堆的石子数,每两个数之间用一个空格分隔。 输出: 合并的最小得分,每个结果一行。 输入样例: 4 4 4 5 9 6 3 4 6 5 4 2 0 输出样例: 43 61 分析最优解的结构: 假设有石头Ai,Ai+1,……,Ai+j-1共j堆需要合并,简记为A[i+0,i+j-1].如果设最后一次合并发生在Ak与Ak+1之间(i<=k <=i+j-1),则最后一个合并的得分为 Ai,Ai+1,……,Ai+j-1堆石头的个数的总和记为totalValue(i,j).(不管你最后一次合并发生在哪个位置