`
200830740306
  • 浏览: 109409 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

动态规划经典问题 石子合并

阅读更多
我们学校的oj的
#include <stdio.h>
#include <memory.h>
int sum[105][105] = {0};//合并后的状态分
int dp[105][105] = {0};//见下面注释
int p[105] = {0};
int n;

int dpMax(int start, int length) {
    int k, temp = 0;
    if (dp[start][length] != -1) {
        return dp[start][length]; //已经求过
    }
    dp[start][length] = 0;
    //枚举划分的情况
    for (k = 1; k <= length - 1; k++) {
        temp = dpMax(start, k) + dpMax((start + k - 1) % n + 1, length - k)
                + sum[start][length];
        if (temp > dp[start][length]) {
            dp[start][length] = temp;
        }
    }
    return dp[start][length];
}

int dpMin(int start, int length) {

    int k, temp = 0;
    if (dp[start][length] != -1) {
        return dp[start][length]; //已经求过
    }
    dp[start][length] = 32767;
    if (length == 1) {
        dp[start][length] = 0;
    }
    //枚举划分的情况
    for (k = 1; k <= length - 1; k++) {
        temp = dpMin(start, k) + dpMin((start + k - 1) % n + 1, length - k)
                + sum[start][length];
        if (temp < dp[start][length]) {
            dp[start][length] = temp;
        }
    }
    return dp[start][length];
}

/*
 * 动态规划经典问题 石子合并
 * 感谢黄大牛!!!
 * 在一个圆形操场的四周摆放着n 堆石子。
 * 现要将石子有次序地合并成一堆。
 * 规定每次只能选相邻的2 堆石子合并成新的一堆,
 * 并将新的一堆石子数记为该次合并的得分。
 * 试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分。
 * input
 * 4
 * 4 4 5 9
 * output
 * 43
 * 54
 *
 * 设dp[i][k]表示以i为起点,长度为k的直线上各堆石子的最优合并状态
 * sum[i][k]表示以i为起点,长度为k的直线上各堆石子的总分
 * 枚举起点,变环为直线
 *
 * 对于每一条长度为k的直线有k-1种划分方法,
 *                  枚举后,就求出最优值
 * 如:4 4 5 9,看成已经合并后的一个大堆,共有3种划分,即
 * 4 459;44 59;445 9;看成是这三种情况下每两个堆的合并
 * dp[1][4]=dp[1][1]+dp[2][3]+sum[1][4]
 *         =dp[1][2]+dp[3][2]+sum[1][4]
 *         =dp[1][3]+dp[4][1]+sum[1][4]
 * 子问题再类似分解
 * dp[2][3]=dp[2][1]+dp[3][2]+sum[2][3]
 *         =dp[2][2]+dp[][]+sum[2][3]
 * dp[2][2]=dp[2][1]+dp[3][1]+sum[2][2]
 * dp[1][2]=dp[1][1]+dp[2][1]+sum[1][2]
 * dp[3][2]=dp[3][1]+dp[4][1]+sum[3][2]
 * dp[1][3]=dp[1][1]+dp[2][2]+sum[1][3]
 *         =dp[1][2]+dp[3][1]+sum[1][3]
 * 而dp[1][1]=4;dp[2][1]=4;dp[3][1]=5;dp[4][1]=9;
 * 从上递归或从下递推都能求得最优值
 * 也就是要把dp[][]和sum[][]这两张表填写完毕
 * 按照假设,这两张表要按列来填
 */
int main() {
    int i, j, max = 0, min = 32767, temp = 0;
    scanf("%d", &n);
    //输入
    for (i = 1; i <= n; i++) {
        scanf("%d", & p[i]);
    }
    memset(sum, 0, sizeof (sum));
    //填求和的表,按列填
    //第一列
    for (i = 1; i <= n; i++) {
        sum[i][1] = p[i];
    }
    //余下的
    for (j = 2; j <= n; j++) {
        for (i = 1; i <= n; i++) {
            sum[i][j] = sum[i % n + 1][j - 1] + sum[i][1]; //
        }
    }
    //
    memset(dp, -1, sizeof (dp));
    //枚举起点,变环为线
    for (i = 1; i <= n; i++) {
        temp = dpMin(i, n);
        if (temp < min) {
            min = temp;
        }
    }
    memset(dp, -1, sizeof (dp));
    //枚举起点,变环为线
    for (i = 1; i <= n; i++) {
        temp = dpMax(i, n);
        if (temp > max) {
            max = temp;
        }
    }
    printf("%d\n", min);
//    for(i=1;i<=n;i++){
//        for(int j=1;j<=n;j++){
//            printf("%d ",sum[i][j]);
//        }
//        printf("\n");
//    }
    printf("%d\n", max);

    return 1;
}

分享到:
评论

相关推荐

    石子合并问题的 动态规划解法

    解题思路:类似于矩阵连乘问题,可以用动态规划的方法来解决: (1)定义一个n*n的数组A来存储合并石子的最小合并方式,由一开始的只有两堆石子要合并慢慢向上递归得到n堆石子合并的最小得分。 (2)定义另一个...

    动态规划 解决石子合并问题

    动态规划 解决石子合并问题 在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。规定每次只 能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出...

    动态规划解石子合并问题

    总的来说,动态规划解石子合并问题是一种通过合理规划合并顺序以达到最低能耗的策略。这个问题展示了动态规划在处理具有复杂依赖关系的优化问题上的强大能力,同时也体现了C++作为编程语言在算法实现上的效率和灵活...

    石子合并 问题 动态规划 源码

    用 动态规划 解决 石子合并 问题 用 动态规划 解决 石子合并 问题 用 动态规划 解决 石子合并 问题

    【算法设计分析课程设计】动态规划解决石子合并问题及回溯法解决运动员匹配问题

    针对石子合并问题,本文利用动态规划算法寻求石子合并时的最大,最小得分,选择相邻的两堆石子堆进行合并,其最终花费的代价与石子堆的排列顺序有关。根据其重叠子问题建立状态转移方程,利用程序进行求解。算例结果...

    9动态规划算法2-石子合并.doc

    石子合并问题是动态规划算法的一个经典应用场景。在这个问题中,我们需要将一些石子合并成一个大的石子,以便于更好地处理和存储。下面我们将详细介绍动态规划算法在石子合并问题中的应用。 一、问题描述 石子合并...

    石子合并问题 用动态规划方法

    ### 石子合并问题与动态规划 #### 一、问题背景及定义 在计算机科学领域,特别是算法设计中,石子合并问题是常见的一个问题。该问题通常可以这样描述:假设有一行排布的N个石子,每个石子有一个特定的分数。玩家的...

    不能移动的石子合并问题(动态规划/C++实现)

    第一个石子合并模型,和书上3.1节的矩阵连乘问题类似. 假设m[i,j]为合并石子ai…aj, 1≤i≤j≤n,所得到的最小得分,若没有“合并”这个动作,则为0。原问题所求的合并最小值即为m[1,n]。 递推公式如下,其中min表示...

    算法设计与分析:石子合并问题

    石子合并问题是一个典型的动态规划问题,它源于实际生活中的操作,如游戏或资源优化等场景。在这个问题中,我们面临一个圆形操场上的n堆石子,目标是通过相邻两堆石子的合并,最终形成一堆。每次合并会产生一个得分...

    动态规划石子合并问题

    在一个圆形操场的四周摆放着n 堆石子。...规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分。源代码

    石子合并 在一个圆形操场的四周摆放着 n 堆石子. 现要将石子有次序地合并成一堆, 规定每次只能选相邻的 2 堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分.

    石子合并问题是在计算机科学领域中一种经典的动态规划问题,它涉及到数组、循环、动态规划算法以及位运算等核心概念。在这个问题中,我们需要在一个圆形操场的周围放置一系列的石子堆,并按照特定的规则将这些石子堆...

    C/C++实现石子合并

    在本课程设计中,我们探讨的是“C/C++实现石子合并”这一经典算法问题。这个问题通常被用来考察程序员对数据结构和算法的理解,以及如何有效地解决实际问题的能力。在这个圆形操场上的问题中,我们可以将其想象为有...

    ACM经典题目石子合并

    动态规划典型题目:在一个圆形操场的四周摆放着n堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。试设计一个算法,计算出将n堆石子合并成...

    动态规划专题之合并石子问题1

    在IT领域,动态规划是一种强大的算法,用于解决最优化问题,通过将...总的来说,这个动态规划问题提供了一个将多个子问题组合成一个全局最优解的实例,通过自顶向下和自底向上的策略展示了动态规划的灵活性和实用性。

    石子合并问题

    3. **动态规划**:虽然这个问题可以通过贪心策略解决,但它也可以被看作是一个动态规划问题。我们可以建立一个状态表示当前有多少个堆,每个堆的大小是什么,然后找出从这个状态转移到下一个状态的最小代价。 4. **...

    11079 可以移动的石子合并

    11079 可以移动的石子合并 时间限制:1000MS 内存限制:1000K 提交次数:0 通过次数:0 题型: 编程题 语言: 无限制 Description 有n堆石子形成一行(a1,a2,…,an,ai为第i堆石子个数),现要将石子合并成一堆,规定...

    n堆石子合并问题-动态规划.docx

    在算法分析的世界中,有一种经典的问题——n堆石子合并问题,它巧妙地展示了动态规划在解决复杂优化问题中的威力。问题的核心在于,如何以最少或最多的得分,将圆形操场边缘的n堆石子逐次合并成一堆。下面,我们将...

    石子合并问题代码

    算法分析课程作业,C语言编写,可能需要用input.txt输入,石子合并问题代码

Global site tag (gtag.js) - Google Analytics