算法提高 合并石子

咳咳:一句题外话: 欢迎访问我的个人博客何俊才个人博客,这是基于NodeJS独立搭建的博客,代码基本上都是自己一行一行的码出来的。有很多不完善的地方希望访问这篇博文的阅读者给出建议。以便我更好的改进。(因为是学习所以有些框架就没用,在自己能力范围之内能实现的就自己手动实现)
说两句题外话:带我专业入门的朋友曾经向我提起,每段时间的复习特别有必要,比你一味的码代码,而不知到复习的效率不知到要高多少。现在深有体会,蓝桥上面的题第一次做很受打击,经常性的不知道如何下手。。。。但还是慢慢的坚持了下来,虽然好多题都是依靠csdn做出来的,但是不得不否认这个过程中学到了很多知识,填补了很多知识空白,也感叹前人的智慧。这段时间,把做的题复习了一遍,不说,收获还挺大的,好多以前不理解的知识点,随着自己的理解,不停的调试程序,慢慢的也就明白了。也就那么回事(废话有点多了)。当然自己写上来的东西肯定有错,也希望大家指正,一起进步。


这道题和上次的矩阵相乘的题很相似,都是找最小值。所以动规的思想是一样的(这里是否可以延伸,涉及到类似线性的动规问题,动规的处理是一样的)。我觉得处理动规问题只要知道dp[i][j] i和j在这个题中的所要代表的意义,那么这个题也就解决一半了。
这道题和矩阵相乘那道题唯一有点不同的是要首先计算一下堆与堆的距离。因为dp[i][j]表示i堆到j堆的最小花费,所以需要把i堆到j堆的花费给加上。具体思路可以参照我上篇博客里面说的。

注意:这里对DP算法有个优化,这是和矩阵相乘那个题处理不一样的地方。因为那道题时间限制是3s,本题限制是2s。所以需要优化。具体优化是设立一个临时变量minx,来存放t的值,最里一层for循环完了才把minx的值给dp,这里对dp数组的操作就减少了,效率也就提升上去了,有零点几秒的提升.
#include<stdio.h>
#include<stdlib.h>
#define INIF 999999999
int N;
int dp[1001][1001] = { 0 };//第一个石子和最后一个石子的 
int sum[1001][1001];
int num[1001];
void minsz() {
	int i, j, k, t, len,minx;
	for (i = 1; i <= N; i++) {
		sum[i][i] = num[i];
		for (j = i + 1; j <= N; j++) {
			sum[i][j] = sum[i][j - 1] + num[j];//计算堆到堆的距离
		}
	}
	for(j=2;j<=N;j++){
		for(i=j-1;i>0;i--){
			minx=INIF;
			dp[i][j]=INIF;
			for(k=i;k<j;k++){
				t=dp[i][k]+dp[k+1][j]+sum[i][j];
				if(t<minx) minx = t;
			}
			dp[i][j]=minx;
		}
	} 
	printf("%d\n", dp[1][N]);

}

int main(void) {
	int i;
	scanf("%d", &N);
	for (i = 1; i <= N; i++) {
		scanf("%d", &num[i]);
	}
	minsz();
	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值