石子问题(直线型)

// 好久没写C语言代码, 今天学习一个石子问题, 解决CCF的压缩编码的问题
// (1)有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动
// 相邻的2堆石子合并,合并花费为新合成的一堆石子的数量。求将这N堆石
// 子合并成一堆的总花费最小(或最大)。

// 什么是动态规划
// 动态规划常常采取从部分整体最优解的拆分来得到最优解法的递归式,我
// 们可以想到,此处是由2堆石子合并,所以最终最优解肯定是由两个局部
// 最优解的加上整体的和求得。
#include <stdio.h>
#define INIF 999999999
int dp[1001][1001] = {0};
int sum[1001][1001];
int num[1001];
int n;

void runDp();
int main(void) {
    FILE* fp = fopen("num.txt", "r");
    int i = 0;
    fscanf(fp, "%d", &n);
    // 设置一个长度为10001的数组
    // 将数据输入
    fp = fopen("data.txt", "r");

    for (i = 1; i <= n; i++) {
        fscanf(fp, "%d", &num[i]);
        // 数据进去了 printf("数据:%d\n", num[i]);
    }

    runDp();

    return 0;
}
void runDp() {
    int i, j, k, t, len, min;
    // 计算堆与堆之间的距离
    for (i = 1; i <= n; i++) {
        sum[i][i] = num[i];
        for (j = i+1; j <= n; j++) {
            // sum 是i到j-1 合并 所产生的花费 最后加上 合并[j]
            sum[i][j] = sum[i][j-1] + num[j];
        }
    }
    // 首先是长度
    for(j = 2; j <= n; j++) {
        // 从第一个开始算起, 这个长度下, 的最小值
        // 然后是从后往前算,
        // dp的意思好像是合并
        // sum的意思应该就是, 合并这两个堆, 不移动的花费, 只是中间过程
        // 才是我们要想的
        for(i = j-1; i >= 0; i--) {
            min = dp[i][j] = INIF;
            for(k = i; k < j; k++) {
                // k 在这里, 就是更新最小值的
                // 所以, 要把所有的遍历一遍,
                // dp[][]里的值都是最小的, 所以要从后往前
                t = dp[i][k] + dp[k+1][j] + sum[i][j];
                if(t < min) { min = t; }
            }
            dp[i][j] = min;
        }
    }
    printf("%d\n", dp[1][n]);
    return;
}

不知道为什么Git, 传不上去....所以我又回来了....

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值