7-10 石子合并 (10 分)(1)

言尽于此,完结

无论是一个初级的 coder,高级的程序员,还是顶级的系统架构师,应该都有深刻的领会到设计模式的重要性。

  • 第一,设计模式能让专业人之间交流方便,如下:

程序员A:这里我用了XXX设计模式

程序员B:那我大致了解你程序的设计思路了

  • 第二,易维护

项目经理:今天客户有这样一个需求…

程序员:明白了,这里我使用了XXX设计模式,所以改起来很快

  • 第三,设计模式是编程经验的总结

程序员A:B,你怎么想到要这样去构建你的代码

程序员B:在我学习了XXX设计模式之后,好像自然而然就感觉这样写能避免一些问题

  • 第四,学习设计模式并不是必须的

程序员A:B,你这段代码使用的是XXX设计模式对吗?

程序员B:不好意思,我没有学习过设计模式,但是我的经验告诉我是这样写的

image

从设计思想解读开源框架,一步一步到Spring、Spring5、SpringMVC、MyBatis等源码解读,我都已收集整理全套,篇幅有限,这块只是详细的解说了23种设计模式,整理的文件如下图一览无余!

image

搜集费时费力,能看到此处的都是真爱!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

3.求其递推方程

其递推方程:m[i][j] = m[i][k]+m[k+1][j] + sum [j] - sum [i -1];

4.递推方程的解释:

前面的m[i][k] 和 m[k+1][j] :i到k合并成一堆,k+1到j又合并成一堆

后面的sum[j] - sum[i -1]: 这里表示的是刚形成的两堆 再合并到一块的石子数

也就是用前缀和来求区间和

比如有(1,2,3,4,5,6)这里表示的是有6堆石子

现在我们求m[3][6] = m[3][4]+m[5][6] + sum[6] - sum[2]

sum[6]:表示的是将这6堆全部合并在一起

sum[2]:表示的是将前两堆合并在一起

现在我们要求后4堆的和 那不就是sum[6] - sum [2];

*/

// 我们要求的是最小次数

#include<bits/stdc++.h>

using namespace std;

#define infinite 99

int main(){

int N;

int m[100][100];//注意二维数组不能开的太大

cin >> N;

int sum[N+1];//求前缀和

int a[N+1];//记录每堆的石子数量

//因为我们要求的是最小次数 故我们将数组先进行赋最大值

for(int i = 0; i < 100; i++){

for(int j = 0; j < 100; j++){

m[i][j] = infinite;

}

}

for(int i = 1; i <= N; i++){

cin >> a[i];

sum[i] = sum[i-1] + a[i];//记录前缀和

m[i][i] = 0;//自己 到自己肯定不能合并啊

}

// for(int i = 0; i <= N; i++){

// cout << sum[i] << ’ ';

// }

//

//开始更新网格

for(int i = N; i >= 1; i–){

for(int j = i + 1; j <= N; j++){//这里的i+1是指的是在i后面进行划分

m[i][j] = m[i][i] + m[i+1][j] + sum[j] - sum[i - 1];

for(int k = i+1; k < j; k++){//这里的i+1指的是在i后面进行划分 k < j 指的是k在j之前划分

int temp = m[i][k] + m[k+1][j] + sum[j] - sum[i-1];

if(temp < m[i][j]){

m[i][j] = temp;

}

}

}

}

// for(int i = 1; i <= N; i++){

// for(int j = 1; j <= N; j++){

// cout << m[i][j] << ’ ’ << ’ ’ << ’ ’ << ’ ';

// }

// cout << endl;

// }

cout << m[1][N];

}

//测试用例一:

//5

//1 3 4 2 5

//34

//测试用例二:

//4

//4 5 9 4

//0 9 27 44

//0 0 14 31

//0 0 0 13

//0 0 0 0

//44

三:石子合并(环形 (本题题解7-10))

====================================================================================

1.题目:


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

试设计出一个算法,计算出将 N 堆石子合并成 1 堆的最小得分和最大得分。

输入格式:

数据的第 1 行是正整数 N ,表示有 N 堆石子。

第 2 行有 N 个整数,第 i 个整数 a

i

表示第 i 堆石子的个数。

输出格式:

输出共 2 行,第 1 行为最小得分,第 2 行为最大得分。

输入样例:

4

4 5 9 4

输出样例:

43

54

2.思路:


思路:这里是环形的,我们把环形的每次连接的地方依次剪开,变成链型的

那么就有一种思路 就是将输入的数组复制两次,那么的话,我们每次一次

取出N个元素,就实现了,不同的链接处的分割,然后求出最后结果时候

根据划分的不同我们按最大或或最小值选取最后的结果

3.上码:


/**

思路:这里是环形的,我们把环形的每次连接的地方依次剪开,变成链型的

那么就有一种思路 就是将输入的数组复制两次,那么的话,我们每次一次

取出N个元素,就实现了,不同的链接处的分割

*/

#include<bits/stdc++.h>

using namespace std;

int main(){

int N;

int max_tone[300][300];

int min_tone[300][300];

cin >> N;

int a[2*N+1];

int sum[2*N+1];

sum[0] = 0;//需要给sum[0] 赋初值,否则sum[0] 是个很大的数

// //注意下方的代码:数组的列均变为原来的2倍 行是不变的

// for(int i = 0; i <= N; i++){

// for(int j = 0; j <= 2*N; j++){

// max_tone[i][j] = 0;

// min_tone[i][j] = 9999;

// }

// }

for(int i = 1; i <= N; i++){

cin >> a[i];

a[i+N] = a[i];

}

for(int i = 1; i <= 2*N; i++){

sum[i] = sum[i-1] + a[i];

max_tone[i][i] = 0;

min_tone[i][i] = 0;

}

// for(int i = 0; i <= 2*N; i++){

// cout << sum[i] << ’ ';

// }

//

//开始更新网格

for(int i = 2*N; i >= 1; i–){

for(int j = i+1; j < i+N && j <= 2*N; j++){//这里的j < i+N,是确定每次划分的范围为N个

max_tone[i][j] = max_tone[i][i] + max_tone[i+1][j] + sum[j] - sum[i-1];

min_tone[i][j] = min_tone[i][i] + min_tone[i+1][j] + sum[j] - sum[i-1];

for(int k = i + 1; k < j; k++){

int temp1 = max_tone[i][k] + max_tone[k+1][j] + sum[j] - sum[i-1];

int temp2 = min_tone[i][k] + min_tone[k+1][j] + sum[j] - sum[i-1];

//求取最大值

if(temp1 > max_tone[i][j]){

max_tone[i][j] = temp1;

}

//求取最小值

if(temp2 < min_tone[i][j]){

min_tone[i][j] = temp2;

}

}

}

}

//

// for(int i = 1; i <= N; i++){

// for(int j = 1; j <= 2*N; j++){

// cout << min_tone[i][j] << ’ ';

// }

// cout << endl;

// }

//因为 我们从合并的两个数组中每次选取出N个元素,即1到N,2到N+1,N到i+N-1为止,再往下就出现重复了

int maxx = 0,minn = 9999;

for(int i = 1; i <= N; i++){

maxx = max(max_tone[i][i+N-1],maxx);

minn = min(min_tone[i][i+N-1],minn);

}

cout << minn << endl << maxx;

}

//4

//4 5 9 4

//0 9 27 44 0 0 0 0

面试资料整理汇总

成功从小公司跳槽进蚂蚁定级P7,只因刷了七遍这些面试真题

成功从小公司跳槽进蚂蚁定级P7,只因刷了七遍这些面试真题

这些面试题是我朋友进阿里前狂刷七遍以上的面试资料,由于面试文档很多,内容更多,没有办法一一为大家展示出来,所以只好为大家节选出来了一部分供大家参考。

面试的本质不是考试,而是告诉面试官你会做什么,所以,这些面试资料中提到的技术也是要学会的,不然稍微改动一下你就凉凉了

在这里祝大家能够拿到心仪的offer!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

out << minn << endl << maxx;

}

//4

//4 5 9 4

//0 9 27 44 0 0 0 0

面试资料整理汇总

[外链图片转存中…(img-P8af15MH-1715798987087)]

[外链图片转存中…(img-W4IaGIjq-1715798987087)]

这些面试题是我朋友进阿里前狂刷七遍以上的面试资料,由于面试文档很多,内容更多,没有办法一一为大家展示出来,所以只好为大家节选出来了一部分供大家参考。

面试的本质不是考试,而是告诉面试官你会做什么,所以,这些面试资料中提到的技术也是要学会的,不然稍微改动一下你就凉凉了

在这里祝大家能够拿到心仪的offer!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值