| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 9.6 a.m.小结 -> 正文阅读 |
|
[C++知识库]9.6 a.m.小结 |
T1:问题 A: 石子合并题目描述??? 在一个圆形操场的四周摆放了n堆石子(n< 100),现要将石子有次序地合并成一堆。规定每次只能选相邻的两地合并成新的一堆, 并将新的一堆的石子数记为该次合并的得分。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 图1 样例所示的4堆石子 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 图2 样例所示得分总和最小的方案 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 图3 样例所示得分总和最大的方案 输入第1行为石子堆数,第2行为每堆石子数,每两个数之间用一个空格分隔。 输出第1行为最小得分值,第2行为最大得分值。 样例输入4 4 5 9 4 样例输出43 54 题解 首先看看这道题是不是贪心。根据最初的想法,每次选取和最大或最小的石子进行合并。但是试过几组数据发现,这种贪心方式是错误的。因此我们来考虑dp。由于题目规定只能把相邻的两堆进行合并,因此很容易想到区间dp。但是由于这是一个环,因此先把环扩展为链,再进行区间处理。首先最外层肯定枚举区间长度,然后枚举左端点,自然右端点也就出来了。然后怎么转移呢,可以由两个小区间合并而来,所以第三维再枚举一个端点就行了注意是2个dp。 参考代码
T2:问题 B: 对抗赛题目描述程序设计对抗赛设有 N(0<N≤50 的整数)个价值互不相同的奖品,每个奖品的价值分别为 S1,S2,S3……Sn(均为不超过 100 的正整数)。现将它们分给甲乙两队,为了使得甲乙两队得到相同价值的奖品,必须将这 N 个奖品分成总价值相等的两组。 输入第一行一个整数N; 输出一行一个整数,表示多少种分法的答案,数据若无解,则输出?0。 样例输入7 1 2 3 4 5 6 7 样例输出4 题解 这道题是一道存在性背包的题,其一明显的性质就是价值和并不大。于是我们枚举每一个数,再枚举每一种可能的价值,用桶来存,于是经过一遍扫描后,就可以得到所有可能的和,然后再看是否有价值总和一半的情况,并直接输出个数即可。注意,我们所求的是所有答案是总和一半的组合情况,由于两种组合是一种分法,因此最后还要除以2才是答案。 参考代码
T3:问题 C: 演讲大厅安排题目描述有一个演讲大厅需要我们管理,演讲者们事先定好了需要演讲的起始时间和中止时间。我们想让演讲大厅得到最大可能的使用。我们要接受一些预定而拒绝其他的预定,目标是使演讲者使用大厅的时间最长。假设在某一时刻一个演讲结束,另一个演讲就可以立即开始。 输入第一行为一个整数 N,N≤5000,表示申请的数目。 输出一个整数,表示大厅最大可能的使用时间。 样例输入12 1 2 3 5 0 4 6 8 7 13 4 6 9 10 9 12 11 14 15 19 14 16 18 20 样例输出16 题解 这道题其实运用了贪心的思想,还是枚举每个时间段,只不过要想一个策略使该种贪心方法无后效性,即贪一个放一个。因此我们可以先左端点排序,在左端点相同时,再按照右端点排序,再枚举之前所有时间,看看有无冲突,没有就转移,因此我们还是要用到dp,只不过是在贪心的基础上完成的。这样做是O(n*n)的效率。那么有没有更好的方法呢?其实我们完全可以维护一个单调队列,每次二分查找第一个与之不冲突的时间,并且用sum数组来记录每一个单调队列中的最大值,这样配合二分就可以log地完成当前时间段的转移。此处给出第一种朴素的算法代码。 参考代码
T4:问题 D: 传纸条题目描述小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个 m 行 n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。 输入第一行有 2 个用空格隔开的整数 m 和 n,表示班里有 m 行 n 列(1<=m,n<=50)。 输出共一行,包含一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。 样例输入3 3 0 3 9 2 8 5 5 7 0 样例输出34 提示【限制】 题解 最朴素的方法,搜呗。把50拆成25和25,这样效率完全过得去。好了,现在来讲讲另一种方法,一种4维dp。维度其实很好理解了,分别是第一个点的横纵坐标和第二个点的横纵坐标。由于本题是先从左上角走到右下角,再从右下角走到左上角,所以我们可以看作两个点同时从左上角出发,通向右下角。我们还能保证一点,就是我们可以视作两个点速度一样,因为两个点的曼哈顿距离是一样的(曼哈顿距离就是从A位置走到B位置所需的最小步数),又由于两个点不能相遇,所以我们可以视为每时每刻两个点都不会相遇。将问题转化到这里时,我们现在来考虑dp转移。其实有4种转移方式(每个点有2种,从左或从上),就算是不合法的转移,因为我们dp的初值是0,而我们所求的是max,所以也不会影响答案。现在来到最关键的一点:枚举顺序。我们首先要明确一点,就是两个点根本不能相遇,也就更不能交叉,所以必然是一个点在下,一个点在上,搜索的时候依照这一点也能省很多效率.....先不说搜索了,言归正传,于是我们可以定义第一个点的横坐标在相同时刻一定小于第二个点。那我们该从何枚举起呢?自然就是两个点的曼哈顿距离了,然后分别枚举两个点的横坐标就可以确定两个点的坐标。因此这道题就是一道经典的坐标式的dp题目。 参考代码
T5:问题 E: 守望者的逃离题目描述恶魔猎手尤迪安野心勃勃,他背叛了暗夜精灵,率领深藏在海底的娜迦族企图叛变。守望者在与尤迪安的交锋中遭遇了围杀,被困在一个荒芜的大岛上。为了杀死守望者,尤迪安开始对这个荒岛施咒,这座岛很快就会沉下去。到那时,岛上的所有人都会遇难。守望者的跑步速度为 17m/s,以这样的速度是无法逃离荒岛的。庆幸的是守望者拥有闪烁法术,可在1s 内移动 60m,不过每次使用闪烁法术都会消耗魔法值 10 点。守望者的魔法值恢复的速度为 4 点/s,只有处在原地休息状态时才能恢复。 输入仅一行,包括空格隔开的三个非负整数 M, S, T。 输出包含两行: 样例输入39 200 4 样例输出No 197 提示
题解 严格来说,这题不算dp,更像贪心。由于我们知道,闪现肯定在大多数时候是更优的,因此能闪就闪,不能闪就回蓝。但是也会出现闪现等待不如直接往前走的情况,所以我们要同时进行:既有一个s来存走路的,还有一个s来枚举闪现的。一旦走路的没闪现快,就把走路的换成闪现的。每次拿走路的与最终ans比较大小,即可得出正确答案。下面给出的代码以特判为主,所以比较冗杂,但也没有漏掉情况。 参考代码
T6:问题 F: 矩阵取数游戏题目描述帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数。游戏规则如下: 输入包括 n+1 行: 输出仅包含 1 行,为一个整数,即输入矩阵取数后的最大得分。 样例输入2 3 1 2 3 3 4 2 样例输出82 提示【样例 1 解释】 题解 这道题目前只分享一下思路(状压好打,高精不好打........),首先明白每一行与其他行是互不影响的,因此我们来看某一行。由于该题目是要么从左端取,要么从右端取,因此dp[i][j]表示从左边取了i个,从右边取了j个的最大得分,转移方程也很简单,就是当i不等于0时,看能否由dp[i-1][j]转移而来,同理对于j也是这样。最外层可以枚举一下现在已经取了多少个了,因此最后直接求所有dp[i][j],i+j=当前行总个数,中的最大值,就作为当前行的答案。代码请参考洛谷。 T7:问题 G: 城市交通题目描述? ? 有n个城市,编号1~n,有些城市之间有路相连,有些则没有,有路则会有一个距离。图所示为一个含有11个城市的交通图,连线上的数(权)表示距离。现在规定只能从编号小的城市到编号大的城市。问:从编号为1的城市到编号为n的城市之间的最短距离是多少? 输入第1行为n,表示城市数,n≤100。 输出一行一个数,表示最短距离。数据保证-定可以从城市1到城市n。 样例输入11 05300000000 50016300000 30008040000 01000005600 06800005000 03000000080 00400000030 00055000003 00060000004 00000830003 00000003430 样例输出13 提示【问题分析]】
题解 这道题用逆向思维的动规来解决是很容易的,如果你要用图论中的方法(FLOYD、DJ等),那就要注意,只能是标号小的到编号大的,因此还要加一句判断,才能得到正确答案。总的来说,一道基础的图的dp题。哦,还有一道巨坑的地方,输入是n行n列的邻接矩阵,所以输入不能输入字符串(当然是可以直接字符串的)。 参考代码
T8:问题 I: 玩具装箱题目描述P 教授要去看奥运,但是他舍不得他的玩具,于是他决定把所有的玩具运到北京。 为了方便整理,P 教授要求在一个一维容器中,玩具的编号是连续的;同时,如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物。形式地说,如果要将 i 号玩具到 j 号玩具(i≤j) 放到同一个容器中,则容器长度不小于 ? 制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为 x,其制作费用为 (X?L)2?,其中 L 是一个常量。 输入第一行输入两个整数 N,L; 输出输出最小费用。 样例输入5 4 3 4 2 1 4 样例输出1 提示【数据范围与提示】 ? ? 题解 这道题数据强度比较大,因此判定是dp。,我们定义dp[i]表示前i个玩具被装入容器的最小费用,现在我们来看一下,对于任意一个状态,能否转移。假设我们如今枚举到第i个玩具,并且在i之前有dp[j]已经求出,那么我们需要把第j+1到i个玩具装入一个新的容器,即: (0<j<i) ? 其中:sum[i]表示玩具长度的前缀和。 这样我们可以通过O(n*n)来得到答案。但是这样明显是不够的,我们需要对这个式子进行优化。由于这个式子中出现了平方,因此我们思考能否用斜率优化。 思考有如下状态,我们思考i应该由j转移而来还是由k转移。为了使问题简化,我们定义: ? ? 为了判断这一点,我们来做差比大小:
? 我们发现了什么?这是一个斜率式!点坐标为(b[i],)。 ? 这样有何意义?假设我们将2个点的斜率表示为slope(j,k),那么当且j<k<i时,显然k更优。因此转化为图像语言为:我们需要维护一个斜率单调递增的队列。一旦我们发现当加入i这点进来后出现了斜率下降的情况,我们就需要先将队列中的元素清除一部分,直到满足条件时,就可以将i压入队。如果我们发现队前面有部分不满足i,那么使队头++。 ? 这样我们每次直接取队首,就是所有满足条件的点中y坐标最小的,也就是答案最小的。见下图: ? 由于slope(B,C)>slope(A,B),我们就可以将C入队,否则就需要将B出队....直到满足条件。可以证明,当j<k<i且三者同时在队中时,k一定不是最优的,因此可以通过加入的i清除掉一些无用的元素。 显然,我们最后的答案就是dp[n]。 参考代码
T9:问题 J: 最长公共上升子序列题目描述熊大妈的奶牛在小沐沐的熏陶下开始研究信息题目。 小沐沐先让奶牛研究了最长上升子序列,再让他们研究了最长公共子序列,现在又让他们研究最长公共上升子序列了。 小沐沐说,对于两个数列A和B,如果它们都包含一段位置不一定连续的数,且数值是严格递增的,那么称这一段数是两个数列的公共上升子序列,而所有的公共上升子序列中最长的就是最长公共上升子序列了。 奶牛半懂不懂,小沐沐要你来告诉奶牛什么是最长公共上升子序列。 不过,只要告诉奶牛它的长度就可以了。 数列A和B的长度均不超过3000。 输入第一行包含一个整数N,表示数列A,B的长度。 第二行包含N个整数,表示数列A。 第三行包含N个整数,表示数列B。 输出输出一个整数,表示最长公共子序列的长度。 样例输入4 2 2 1 3 2 1 2 3 样例输出2 提示1≤N≤3000,序列中的数字均不超过231?1 题解 这是一道基础的dp进阶。我们可以定义dp[i][j]表示A1到i中,过Bj的最长公共上升子序列的长度。转移的话就很简单,如果a[i]!=b[j],那么直接dp[i][j]=dp[i-1][j],而如果相等,就可以由之前k状态转移过来,就是:dp[i][j]=max(dp[i][j],dp[i-1][k]+1)。但是这是一道O(n*n*n)的效率,所以我们需要优化。这道题当然不需要像之前那样斜率优化,只需要单调队列优化就可以很容易用O(n*n)来解决这道题。我们可以很容易发现,在我们进行第2维循环时重复计算了许多步骤,我们能否将求最大值的过程简化?自然是可以的。我们来定义val,每次转移就直接val+1,在得到j的答案后,我们尝试将j联系到val中,即if(b[j]<a[i]) ?val=max1(val,dp[i-1][j])。这样就能够在规定效率内完成该题。 参考代码
|
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 20:52:40- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |