问题描述: 在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。 规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。 试设计一个算法,计算出将n堆石子
问题描述:
在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。
规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。
试设计一个算法,计算出将n堆石子合并成一堆的最小得分和最大得分
分析
要求每次合并必须是相邻的,和矩阵链乘的括号作用差不多。可以考虑往矩阵链乘最小代价的递归方程上靠。设dp[i,j]为第i堆到第j堆合并的最优解,则dp[i,j]=mindp[i,k]+dp[k+1,j]+vi+...vjdp[i,j]=min{dp[i,k]+dp[k+1,j]+vi+...vj}dp[i,j]=mindp[i,k]+dp[k+1,j]+vi+...vj
注意由于是圆形,而矩阵链乘是线性的,所以这个递归方程势必需要修改。考虑如何表示环,一个自然的想法是利用mod函数。递归方程修改如下,为了方便表示修改dp[i,j]定义如下:从第i堆开始合并j堆的最优解。(否则需要填写的项数不全在一个矩阵半角上)
dp[i,j]=min{dp[i,k]+dp[(i+k)%n,j−k]+vi+…+vj} i<=k<=j
dp[i,j]=max{dp[i,k]+dp[(i+k)%n,j−k]+vi+…+vj} i<=k<=j
代码展示
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int dp_max[207][207];
int dp_min[207][207];
int cost[207];
int a[203];
const int MAX = 0x3f3f3f3f;int main()
{while(scanf("%d", &n) != EOF){memset(dp_min, MAX, sizeof(dp_min));memset(dp_max, 0, sizeof(dp_max));for(int i = 1; i <= n; i++){scanf("%d", &a[i]);a[i + n] = a[i];dp_min[i][i] = 0;dp_min[i + n][i + n] = 0; }cost[0] = 0;for(int i = 1; i <= 2 * n; i++)//为了后面方便用前缀和cost[i] = cost[i - 1] + a[i];for(int len = 2; len <= n; len++)//走几步 {for(int i = 1; len + i - 1 <= 2 * n; i++)//从哪开始 {int j = len + i - 1;for(int k = i; k < j; k++){dp_min[i][j] = min(dp_min[i][j], dp_min[i][k] + dp_min[k + 1][j] + cost[j] - cost[i - 1]);dp_max[i][j] = max(dp_max[i][j], dp_max[i][k] + dp_max[k + 1][j] + cost[j] - cost[i - 1]);}}}int ans_min = MAX;int ans_max = -1;for(int i = 1; i <= n; i++){ans_min = min(ans_min, dp_min[i][i+n-1]);ans_max = max(ans_max, dp_max[i][i+n-1]);}cout << ans_min << " " << ans_max << endl;}return 0;
}
问题描述: 在一个圆形操场的四周摆放着n 堆石子。现要将石子有次序地合并成一堆。 规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。 试设计一个算法,计算出将n堆石子相关推荐
- 问题描述 给定一个由n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。 对于给定的由n行数字组成的数字三角形,计算从三角形的顶至底
问题描述 给定一个由n行数字组成的数字三角形如下图所示.试设计一个算法,计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大. 对于给定的由n行数字组成的数字三角形,计算从三角形的顶至底的路径 ...
- 数据结构例16.试设计一个算法, 使得在一个有序的单链表中插入一个元素后仍然有序。
/* 16.试设计一个算法, 使得在一个有序的单链表中插入一个元素后仍然有序. */ # include <iostream> # include <stdlib.h> # i ...
- 【一元多项式算法】设一个一元多项式采用带头结点的单链表存储,所有结点 按照升幂方式链接。设计一个算法,求两个多项式 A 和 B 的乘积,结果多项式 C 存放在新辟的空间中。
[一元多项式算法]设一个一元多项式采用带头结点的单链表存储,所有结点 按照升幂方式链接.设计一个算法,求两个多项式 A 和 B 的乘积,结果多项式 C 存放在新辟的空间中. #include<s ...
- P85.2.(2)回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法判定给定的字符序列是否是回文。(提示:将一半的字符入栈)(C语言描述)
做这个题时遇到个bug,即main()中的第一句,我定义了指针str_input用来装输入的字符串,但是后面赋值操作却用了get(),如果要用get()读入字符串的话就应该将str_input定义为数 ...
- 王道综合题17.设计一个算法用于判断带头结点的循环双链表是否对称及其注意思考:while循环第二个判断条件易误写成p->next!=q,分析这样会产生什么问题。
算法思想: 让p从左向右扫描,q从右向左扫描,直到它们指向同一结点(p==q,当循环双链表中结点个数为奇数时)或相邻(p->next=q或q->prior=p,当循环双链表中结点个数为偶数 ...
- [算法]两种水果杂交出一种新水果,现在给新水果取名,要求这个名字中包含了以前两种水果名字的字母,并且这个名字要尽量短。
问题: 两种水果杂交出一种新水果,现在给新水果取名,要求这个名字中包含了以前两种水果名字的字母,并且这个名字要尽量短.也就是说以前的一种水果名字arr1是新水果名字arr的子序列,另一种水果名字arr ...
- 初中计算机新课标培训心得,新课标学习心得体会
新课标学习心得体会由好范文网的会员投稿精心推荐,小编希望以下6篇范文对你的学习工作能带来参考借鉴作用. 第1篇:新课标学习心得体会 新课标学习心得体会怎么写?以下是我们给你的范文格式参考. 用课余时间 ...
- Netflix如何设计一个能满足5倍增长量的时序数据存储新架构?
2016年1月,Netflix在全球范围内扩展业务.越来越多的会员.越来越多的语言和越来越多的视频回放将时间序列数据存储架构扩展到了它的临界点(详见第1部分文章<Netflix实战指南:规模化时 ...
- 计算机专业大学生新学期计划,大学生个人新学期计划
<大学生个人新学期计划>由会员分享,可在线阅读,更多相关<大学生个人新学期计划(11页珍藏版)>请在人人文库网上搜索. 1.True love is visible not t ...
最新文章
- 李洪根关于[SQL]对于分页存储过程
- Vim使用技巧及基本命令分类
- 【CentOS 7MySQL常用操作3】,MySQL常用命令#180113
- TCP/IP网络编程(3)
- Jquery插件之ajaxForm ajaxSubmit的理解用法
- JavaScript:执行上下文执行上下文栈
- selenium课程笔记1---安装与环境配置(selenium,python,pycharm)
- 《代码大全》学习摘要(五)软件构建中的设计(下)
- LayUI使用distpicker.js插件实现三级联动
- 知到计算机绘图网课答案,计算机绘图知到网课答案
- java正则表达式 手机_Java正则表达式
- 好不容易说明白AQS,面试官却还要我说应用场景,我只好又讲了CountDownLatch ~~~
- C#中.snk文件的作用
- CDC::CreateCompatibleDC 的整理(转)
- Netty处理TCP半包和粘包问题
- jhipster快速入门指南
- 交通信号灯控制系统的Verilog实现
- php如何实现文字闪动,Javascrip实现文字跳动特效
- 6种lut预设 CMG Cine LUTs for A7III
- chrome 缺少chrome_elf.dll