洛谷:
p1098:应当充分使用库函数:isalpha(判断字符是否为字母),isdigit(判断字符是否为数字)。
p1065:答案中的now表示当前的零件,step[now]表示这个零件处在哪个步骤
p6363:cmath中round函数表示四舍五入,同时遇到四舍五入的题目应当在前面开double
p1786:sort排序是左闭右开,判断字符串是否相等时“”内多加一个空格都是错误的,应当记住!!!(害得我debug20分钟).....
p1249:将一个数分解成不重复的多个数字,同时使得这些数字乘积最大,应当从贪心角度考虑:
任意一个大于4的自然数,其最大的乘积分解应该以2+3+...+n,这样乘起来才是最大的。
当这串数列大这个自然数1时,可以直接减去2,再在最大数+1,当大于1时,直接减去数列这个数
(反正我是想不到hh)
p1045:sb题目给我恶心死了,用到了快速幂,同时注意j=0,j>=50才是一行50个数而不是j=1
memcpy(a,b,sizeof a)代表将b复制到a中。cmath中自带log10
p1059:去重可用algorithm中的unique函数,该函数返回重复元素之前的一个迭代器,还有int
*i=&a[i](好久不用都忘了hh)
p1116:本题其实就是考察逆序对的数量(但是这题由于数据范围很小所以暴力for循环就可以写出),最好的做法还是用归并(已经忘了特地去看了半个小时)
p5143:cmath中有sqrt函数可以进行开平方根的效果,要想输出保留三位小数的dohle类型可以使用printf("%.3lf",num),注意\n为换行而/n不是(差点搞错..)
p1068:向下取整为floor,向上取整是ceil,而tolower和toupper是将字符转换大小写的(这两类搞混了都)
p1012:采用贪心思想,一定是a+b>b+a(虽然不知道怎么想的),考试中如果实在不会,可以用dfs来暴力搜索(拿点分)
p2241:枚举所有矩形的右下角,正方形为min(i,j),长方形为i*j(不要问我怎么知道的...)记得开long long
p2089:应该用dfs来解决
p1618:用dfs将九个不同的数分成三个不同的部分,再调用另外的函数对这些组成的部分进行特判
p1036:这题终于是我自己写出的第一道暴搜题hh,注意按照普通的dfs需要除以k!,因为dfs
看成每个位置上还要选择但是题目不考虑每个位置的选择。
p1157:本题思路与p1618三连击思路差不多,唯一不同的是这题若是用另外的函数特判(暴力fo
r循环来判断)会导致两个点超时(第一次只拿了80...),一种思路再开一个数组存上一位
的数,这样for循环只要让开始的i等于上一位存的数就可以让后面的数大于上一位的数。iomanip
中的setw函数可以让每个数字有3个场宽。
p1088:本题最简单做法:algortihm中的next_permutation,每运行一次排列出下一个全排序的序
列,左闭右开。当当前排序已经是最大序列,则将这个序列变成最小的排序,并且函数返回值返
回false。
第二种做法是用dfs,因为N最多10000(阶乘可想而知有多恐怖),因此从给出的序列开始求排
序,并且当已经找到需要的序列时就可以直接返回。(不得不说这题真难...)
p3392:这题一开始想用dfs发现根本用不出来...思路是枚举白蓝红的两条分界线,再在两层for循环
中枚举不同分界线情况下需要修改的格子数量取最小值即可。
p3654:又是自己写出来hh,通过暴力枚举每一个点并通过另外的函数来判断,注意k!=1时需
除以2,因为每一条路都会算两遍,但如果k=1时就直接计算所有.即可。
p1149:(自己想用dfs做结果40分钟只是把一位以内的算出来...)通过自订的函数来检测每个数使
用的火柴数,通过计算可知最大为1111,通过枚举所有数来检测。
p3799:先利用桶排序检测所有边长度各个数量,随便两层循环外层循环先枚举两条相同不用合成的
边,随后在内层循环中枚举所有需要合成的边,该边有两种情况首先是该边是两个相同的边合成的
第二种情况是两个不同的边合成该边,注意由于防止重复计算内层循环应当小于i/2,由于该题目
组合数只有1,2两种情况,因此求组合数函数中是特判情况。
p2392:史中史,开始认为贪心可以做并且输入的几个例子都能过结果直接爆0,调到很大的数据才
终于出现错误答案...看了题解用dp做了出来,这题01背包问题,f[i][j]表示左脑处理前i个题目
不超过j分钟解题时间的集合,注意属性为max,因为若为min则1意味着右脑那边就很大,但此题要
求左右脑应该很均衡(因此j不大于这个科目总时间的一半),题目相当于i,时间为j,时间也相
当于01背包的价值...
p2036:一道简单的dfs,不过注意当刚进入dfs时不能一开始就判断差是否最小(因为1,0是人为
输入进去的)。
p1255:如果用暴搜只能拿50,要用到高精度f[i,j],f[i]表示是第i个台阶的方案数,而j是这个方
案数的第j位。由递推得f[i]=f[i-1]+f[i-2],因此需要设置f[1],f[2]。
p1044:注意dp问题应该考虑这一步是由哪种状态转移过来(即上一步的状态),f[i,j]表示i个已
经入栈,j个已经出栈,当f[i,0]时表示上一步一定是入栈,因此f[i,0]=f[i+1,0],因为f[n,0]为
1,所以所有的f[i,0]=1,同时注意i>=j,当i==j时一定是从出栈这一步转移所已只等于f[i,j-1]。
p1028:通过递推可知f[i]=(f[1]+....+f[i/2])+1,因此首先将所有f[i]赋值为1,然后递归的求结
果(看了题解豁然开朗但是自己就是做不出来...)
p1464:首先语法问题:a==b==c==-1和a==-1&&b==-1&&c==-1是不同的,第一个是从左往右依次计算
比较的,首先计算a==b得到一个布尔值,布尔值再和c比较,最后再和-1比较。本题因为递归多次会
导致时间太大,可以用记忆化搜索(即用一个三维数组存放20以内所有的数,当再次用到时直接
用数组里的数据就行),因为当a,b,c<=0和a,b,c>20都已经提前做了处理,所以不存在数组越界的
情况。
p1928:好难...通过递归来实现(根本想不到),不过注意因为递归导致初入最后一个]时依然无法
跳出循环,因此需要在while中cin>>ch改成(ch=getchar())!='\n',并在函数最后加一个return
因为cin会自动忽略换行符
p2437:斐波那契数列:0 1 1 2 3 5....即这一项是前两项的和,本题与数楼梯类似,可以得到递推
式:f[i]=f[i-1]+f[i-2]。符合斐波那契数列,从n到m符合f[n-m+1](第一项从第一个1开始)。因
为斐波那契数列很大(第1000项约1e300),所以必须用高精度
p1164:题目不难,就是初始化想了一会,应该初始化f[i][w[i]]=1.
p1990:(好难啊!!!)这题设f[i]为前i列*2行铺满总面积的方案,当只有长方形的砖头的时候可
以得到f[i]=f[i-1]+f[i-2]。当L形砖头时,设k(i)为前i列都满了,第i列涂了1个。因此可以得到
f[i]=f[i-1]+f[i-2]+2*k[n-1]。又可知k[i]=k[i-1]+f[i-2]。因为存在i-2,所以要将1,2的情况
都初始化。从3开始枚举(代码很简单但是分类很复杂...),注意只输出后4位意味着对1e4取模
(我还以为要用高精度...)
P1259:可以看出当总数2*n+2>=10时有规律可言,当2*n+2<=8时就没有规律,因此在8时进行特判即
可。
p1010:通过简单计算可知2^15一定大于题目给的范围,所以只需要自己手写出1-14的分解方式,然
后从大到小依次求出组成的数(即2的几次方),然后在根据1-14的分解方式就可以轻松求出答案
p1228:(好难...)将一个大的长为2^n的正方形划为四个2^n-1的小正方形,通过分类确定公主在
哪个小正方形,然后另外三个小正方形的三个相邻的顶点就可以铺上一个地毯,然后就可以继续通
过递归将这三个顶点+公主都看成障碍物递归求2^n-2的结果,最后基准情况边长为1就直接返回
(反正我是想不到...)
p1498:好难...递归这边的题目真心难,已经不知道怎么讲了...
https://www.bilibili.com/video/BV18T411u7HG/?spm_id_from=333.788.videopod.sections&vd_source=eaa1685b9a7c0412de82c8ee63c5136b
视频讲的虽然会写但自己单独写写不出来
cmath库中的Pow(2,n)可以返回2^n次方
p1803:基础课的模板贪心题...还是忘了第一次写只拿了20分,需要先依照右端点从小到大进行排
序,然后比较下一个区间的左端是否大于等于此时的ed即可
p1090:轻松的模板题,看到要用最小堆的提示就知道怎么写了。
p3817:稍微难一点的贪心就做不出来了...,本题思路是首先判断第一个盒子是否超过x,如果超过
就减去使得第一个变成x。然后for循环从2开始检测每两个相邻的盒子糖果总数,因为吃第一个盒
子的糖果只会改变一组糖果总数,而吃第二组的糖果数可以改变两组,所以要尽量吃第二组的糖果
这也是为什么要预处理第一个盒子的糖果,第一组处理完再看第二组,因为第二组的第一个是第一
组的第二个,也就是已经处理好了第二组的第一个,只要处理第二个就可以,依次类推就可以。
p1106:自己写了一堆复杂的结果就拿了44分...思路:找到高峰值就直接删掉。要注意前导0.
p5019:题目虽然是贪心但是看完题解觉得用搜索递归会更理解...思路:先找到h到e中的最小值,
将所有路段减去这个最小值,这个时候再通过递归调用h到des-1和des+1到e。sb的是我还在好奇如
果des是一个全局变量那么函数调用它的时候岂不是一直修改,那么递归回来des不是已经不是原来
des了吗?后来才搞懂是值传递,根本不会改变真正的des罢了(基础知识薄弱...)
p4447:第一道绿题(虽然是看的题解...)本题思路:类似于蜘蛛纸牌,将数组排序,然后依次检
测是否有可以放置的位置(即这个堆下一个该放的数字),如果找到则更新下一个该放的数字,并
更新这个堆的大小,如果未找到,则新创建一个堆。可以用algorithm中的lower_bound,使用方法
lower_bound(f+1,f+1+n,q[i])在f[1,n]中找到第一个不小于q[i]的位置,lower_bound返回的是已
排序序列中可以插入目标值的位置,同时保证插入后的序列任然有序,如果全小于q[i].则返回n+1
注意返回的是迭代器,也就是指针因此如果f是数组那么就会返回元素地址因此如果要求数组下标
需要减去一个f。注意插入堆时要保持堆的有序性因此如果需要找到最后一个放该元素的堆。
p1080:目前为止最难的题目...目前功力不够照着把大致代码理解了一下然后跟着写了一下以后慢
慢看...
p1102:以前做过的题只知道大概思路忘记怎么写了...,第一种办法:哈希表unordered_map,将每
个数组元素都映射成s<num,times>即数字和出现次数,随后每个元素减去c,遍历哈希表累加就可
得到答案。第二种办法:利用upper_bound(a[i]>x)和Lower_bound(a[i]>=x)相减得到正好为
a[i]+c的数的个数即可(注意要开long long 不然会爆)
p1837:二分真的好难...此题利用增加高度获得的总值就减少,减小高度总值增加,因此一定是有
序的可以用二分,l为0,r为最高的数,求出tmp临时获得的树数目,如果比需要的少,就要增加
树的数量,即让r=mid-1减小高度增加木材,如果多就要让l=mid+1增加高度减少木材。注意while
循环要l<=r,并且答案为r或者l-1。本题要求尽可能最大的值所以应当往高度大的方向搜因此当
tmp==k时要归到l=mid+1那一类。
p1024:小数的二分,只要让while(r-l>=1e-8)即可,本题先遍历-100到100所有的数,因为两个根
一定差一定大于1所以r=l+1先判断l是否满足方程满足则输出接下来就检测方程(l)和方程(r)
的乘积是否小于0小于0就进入while循环二分查找,注意小数缩小区间直接令l=mid,r=mid即可。
注意求double的平均值不可以用>>.
p1678:可以使用lower_bound,先对学校分数进行排序,然后枚举每个学生分数,利用lower_bound
找到学校分数中不小于学生分数的位置,然后比较前一个位置和当前位置的分数差。注意需要特判
学校分数都小于学生分数和都大于学生分数的情况。要开Longlong!以后所有题目我都开long long
第二种方法就是手卢二分,在二分中创建一个min,记录最小的差,但是二分不依靠这个min,当学
校分数等于学生分数直接返回0,如果学校分数大于学生分数(右边差一定比当前还大)就往左边
搜,如果小于(那么更左边一定大于当前差值)就往右边搜,刚开始想用这个方法结果这个没推出
p2440:算是第一道自己独立做出来的二分...和砍树那题很像,如果数量小于k就减小l,如果大于
k就增加l
p2678:二分的是最小跳跃距离,先构造一个check函数,依次枚举每个石头,如果石头要跳跃的距
离大于等于最小跳跃距离则更新前一个跳跃点,如果小于最小跳跃距离就要增加搬的石头,最后看
所需要搬石头的数量确定false 和true剩下的就是常规二分了。注意如果check成立要开一个ans来
存因为虽然可能右边更好但是可能右边依不行。
p3853:本题与上题类似,唯一的不同是tot的更新,当不符合最优时应当插入新标,而插入新标要
重新检测i,因此要多一个i--。注意要用ans存最后结果不然会显示错误答案。
p1182:这题开始中间想的就有些偏差导致80分后想了好久才理解,首先还是和前几题一样二分最
大值,然后和要求的段数,不同的是,这里的num<m时不一定是错误的因为分的每一段都差不多是
最大值,num<m也可以将每一段都拆分这样最大值还是没有改变,所以当num<=m时是一组,num>m是
一组。
p1163:简单的一道小数二分但是不会推公式...注意不可开辟一个新ans存答案因为小数二分可能不
会等于w0,只会无限接近因此答案是Mid
p3743:对题目理解偏颇,充电并非是普通的充电而是相当于所有设备连接在一个充电宝上,而不是
一段一段充电直到充到所需要的电量。所以二分只要判断总的需要电量和充电宝电量进行对比即可
p1135和p1443;都是简单的bfs应用不过注意的bfs求的一定就是最短路,因为bfs是一层一层向外
搜索,如果存在更短路径,按照一层一层搜索会更早发现。
p2859:一道还是挺难的bfs题,复杂在于对不同时间导致可访问的点不同,因此需要开两个数组,
一个times表示这个点被陨石砸的时间即不可访问的时间(如果无陨石就是-1).vis表示这个节点
是否访问过。还要有一个person的结构体包含人的坐标还有时间。在bfs中人的时间是不断+1的这
样就可以模拟时间的流逝并查看点是否可访问,遇到第一个为times为-1的点就可以直接输出。在
while循环结束就可以直接输出-1。
p1433:一道状态压缩dp问题耗费了我将近3个小时从理解题解到debug完...。首先对于位运算的一
些补充:1<<n表示将n向左移n位表示2^n,dp中最外层的k循环就是这个。f[i][j]表示走到第i个
奶酪且走过的二进制状态j时最短距离。例如当j=110(二进制)表示第二个和第三个点走过。在正式
dp前要对f[i,j]预处理,每一个f[i][1<<(i-1)]=a[0][i],其中f[i][1<<(i-1)]例:i=2时1向左移
动1一位为10表示从起点走到2这个点只经过2,所以就等于a[0][i],i从1开始。而后在三层循环中
第二层循环for(int i=1;i<=n;i++)表示要检查k&(1<<(i-1))是否为0,如果为0意味着此时并没有
包含i这个点就直接continue,如果有i这个点则进入for(int j=1;j<=n;j++)第三层循环首先检查
i==j如果相等直接continue以及重复第二层循环检查j是否在k中。然后就直接写出方程:
f[i,k]=min(f[i,k],f[j][k-(1<<(i-1))]+a[i][j])后面这个式子表示到达j这个点且不经过i这个
点随后再经过i这个点。随后的答案就是从f[i][(1<<n)-1]找出最小值。1<<n表示将1左移n位减去
1则表示都是1,例如1000减去1则表示111.还是表示n个1.状压dp时间复杂度:o(n^2*2^n),通常
只能通过n<=21的数据。
p1605:一道简单dfs...但我居然没看出来以为要用dp结果提交发现只拿了40分析后发现dp的话四个
方向不可能在它之前更新然后用dfs顺利做出。
p1019:好难的一道dfs...,首先要对每个字符串最小重叠数进行计算并预处理为一个二维数组。预
处理中check函数从a(后面要接字符串)从a的末尾遍历至a[0],第二层循环从上一层停留的位置开
始,和b字符串进行比较(正向遍历),如果检测到不同直接退出,如果相同继续遍历如果flag没
有发生变化说明匹配成功就返回i字符串-i(最小折叠),否则返回0.在dfs中,依次遍历每个字符串
,字符串不能超过2次并且要有重合并且两个字符串不可包含关系,即ch[x][i]不可等于x或i的长
。还有一点注意要在dfs中开一个flag,初始为false,如果可以匹配就改成true,在循环结束的末
尾检查flag如果为false表示已经没有可以匹配的字符串就进行赋值。总之这题很难。
p1101:今天又重新想了一下写了一下这题确实是比较奇特的dfs没见过所以没写出来,这题唯一不
同点就是只能朝一个方向遍历还有就是必须整个字符串相等才可以将vis赋为1.第一点不难,难的
是第二点,因此用递归调用。首先检测当前层的x和y是否和字符串对应位置相等并且检查zx和zy是
否在数组范围内,然后再嵌套一个if语句dfs下一层,最后当q>=6即最后一个字符时进行一次检测
如果最后一个也匹配成功则可以递归的将之前几个都赋值为1.
p2404:一道简单dfs,唯一的难点就是怎么去除重合:只要检测他们的排序如果非单调增就直接跳过
p1596:就是一道常规的bfs的题目结果m输成ndebug至少20分钟...下次要注意。
p1162:一道简单bfs题目唯一在做的时候的困扰是突然不知道是否要用vis数组[染色]。问过ai才知
道,在基础课求最短路时,d=-1就相当于已经是vis数组了,如果d不为-1代表说明已经访问过一次。
p1032;一道很狗屎的题目首先这题可以用双向bfs,但是我不会...看题解更更改改。因为当超过
10次就可以直接返回,所以可以开一个struct存每个字符串的更改次数。这题不同于普通的dfs,
这题对于每种可能的情况要在当前字符串从前到末依次检查是否包含r[j]。在已知包含的情况下不
能退出而是还要从下一个位置检测到末尾。因为假如有两个r[j],就意味着会有两种情况,所以在
for循环中还要一个while循环。string的find(string a,pos)从pos这个位置检测是否包含a,如果
包含就返回a出现的起始位置。如果没有则返回-1,rfind则是从后往前搜。replace(pos.num1,string a)
从pos这个位置将num1的长度替换为a。这题最坑的一点是没有告诉你对应的数量,题解中的while
(cin>>r[i]>>l[i) i++;可以在洛谷上过,但是在vs中却会陷入无尽循环....
p1825;一道只需要特判传送门的bfs(但我还是调半天...),首先第一个易错点是传送门的vis不能
变为true。因为有可能一个传送门挡在终点面前,这时就必须经过两次传送才可以到达终点。第二
点也不算坑点:在findsame中(i,j)!=(x,y)应该是i!=x||j!=y而不是i!=x&&j!=y如果(3,4)和(3,5)
时直接跳过了。
p2196:因为数据很水所以dfs可以过,不过需要注意的是题目给出的只能选择一条路,这就导致一
个问题:题目虽然没说通道是单向还是双向,但是因为只能选择一条路径就说明不能返回上一层。
因此道路要设成单向。dfs也需要有dfs,而这个题目的vis就是看有哪些地窖已经经过。
dp做法:f[i]表示以第i个地窖结束的最大数量。可得公式f[i]=max(f[j)+a[i](不是以包不包含
第i-1个划分!!而是以由1,2,3...i过来),路径问题可以使用pre,当f[i]变化直接让pre赋成由哪
一个地窖变到i。
p8824:一道简单模拟不知道为什么可以到普及+的地步...,唯一要注意的是总文件从1开始还是从0
开始,更推荐从1开始,这样的话在touch中需要先更新idx(初始为0)再操作,而从0开始就是最
后再更新idx,不过0比较坑的是最后sort和for循环idx是开区间...
p8825:简单的bfs,唯一注意的是取mod是答案取模(我傻乎乎的让Num也取模导致错了两次),最
后就是pow返回的是double值,所以不能对其取模会报错。
p8838:这道题我想的是贪心(貌似不对),看完题解知道是bfs,依次将每个指令和机器比较看看
是否匹配。因为bfs第一遍深搜就是最小字典序。所以答案出来后令flag为true,标记退出循环,
反正我根本想不到要用bfs...不过似乎难度也不是普及+
p1434:基础课中的一道题目,虽然之前做过但是理解不深:用到了记忆化搜索,什么是记忆化搜索
:将搜过的数据存起来。例如搜(2,2)这个点,如果周围只有(1,2)点符合下一步就搜(1,2)
而为了搜(1,2)只能继续往下搜。这是普通搜索,但如果把(1,2)的数据保存,那么搜(2,2)
就可以直接搜(1,2)。注意在dfs中如果f[x][y]==-1要将f[x][y]赋值为1(这个点本身)
p4017:要用到拓扑排序,入度为0的点就是生产者,出度为0的点就是最高消费者。模板和拓扑排序
差不多,让所有入度为0的点入队列,检测每个点的出度点,将出度点的入度-1,随后利用推出的
公式f[t]+=f[j].如果入度变为0就将这点入队列。最后利用for循环检测有多少个出度为0的点并求和。
p1115:一道很简单的dp问题但我还是没想出来f[i]表示以第i个结尾的序列,可知f[i]=max(f[i-1]+a[i],a[i])
还是题目做的不够多...今天又做了一下发现昨天还是写的很多余...在dp中原先判断这个i-1是否
访问过如果访问过就判断是否大于0,如果没有访问还要手动算一遍,但是本身就已经算出了下一
个i-1即当前i的f,根本不需要这么复杂。只需判断f[i-1]是否大于0即可...
//好多都忘了,持续更新…