【算法竞赛入门经典(第二版)】_要点提取(第三章)

3.1数组

数组大小为常量

对于新手而言,最容易犯的错误就是:在定义数组时,将数组的范围定义成了变量。
错误示范:

int num ;
cin >> num ;
int a[num] ;//错啦!数组范围不能为变量!

但我们偶尔也会利用宏定义来设定数组范围。
什么是“宏定义”?
就是对于整个程序中,给一个常量起个名字,例如:

#define maxn 1010
//将1010起名字叫maxn

x++ 与 ++x

简单来说,对于“x++”,记住:
** 先工作,再加薪! **
也就是说,对于

y = x++ ;

来说,先将x的值赋给y再自己加一 也就是等于

y = x ;
x = x + 1 ;

而对于“++x” ,则是:
** 先加薪,再工作! **

y = ++x ;

等于

x = x + 1 ;
y = x ;

比较大的数组要在main函数外声明!

函数:memcpy()

作者在讲述两个数组a , b之间互相复制的关系时引入了函数memcpy(),并给出了相关操作:

memcpy(b , a , sizeof(int) * k) ;
//将数组 a复制 k 个元素到数组 b
memcpy(b , a , sizeof(a)) ;
//直接取等

还可以推广到 double 类型变量。
该函数的头文件为:

#include <cstring>

接下来作者引入了一道例题。

例一:开灯问题

一道纯种模拟题。我们可以从中学到很多。

初始化的重要性

作者在一开始就提到了初始化的重要性,尤其是在多组输入之中,我们要格外注意。

函数:memset()

那么,我们应该如何解决初始化操作呢?尤其是多维数组,用n个for 嵌套循环实在是太麻烦了。
由此,引入了第二个函数: memset() 。
用法如下:

memset(a , 0 , sizeof(a)) ;

作用:把数组a清零。后面还会有“把数组a全部命名为-1”的操作。我们后续再说。
头文件:

#include<cstring>

取反( ! )符号妙用

一般来说,我们只会在布尔(bool)类型中使用到取反。
作者将他推广到了 int 类型 :
当 int a = 0 时 ,
进行 a = !a 操作就可以使 a = 1

避免输出多余空格的技巧

设置标志变量 first ,记录只在第一行前不输出空格
很好理解的技巧,不多赘述。

例二:蛇形填数

C语言简洁的优势

可以利用C语言简洁的语法,但前提是保持代码的可读性。

先判断,再移动!

而不是走一步以后发现越界了再退回来。这不是强制性要求,但养成良好习惯十分必要。

避免非法访问内存!

通过短路运算符“&&”来保证不会访问非法内存。

3.2 字符数组

本节开篇引入了一个例题来讲解字符数组。

例三:竖式问题

scanf("%s" , s)

作者引入了一个新概念 scanf("%s" , s) 。

他会读入一个不含 空格 、 TAB 、 回车符 的字符串,存入数组s。

由于 s 为字符型数组,直接表示指针,因此可不用"&"(取地址符)。

printf("%5d") 与 printf("%05d")

对于一个数按5位打印,如果小于五位数,前者补空格,后者补0 。

sprintf()

sprintf(buffer , "%d%d%d" , x , y , z) ;
//表示把x , y , z三个数字连在一起输出到字符串buffer
//最后的结果是 buffer 为字符串类型
// 例如 :x = 10(int) , y = 20(int) , z = 30(int)
// buffer = 102030(string)

由此引入了 fprintf(输出到文件) 、printf(输出到屏幕)、sprintf(输出到字符串) 之间的区别。

函数:strlen()

作用:获取字符串实际长度。

下标实际长度
01
12
23
2526

函数:strchr()

strchr(str , a) ;
//在 str 字符串中找 a 字符
//头文件:
#include<cstring>

推广到

strcpy(a , b) ;//赋值b到a
strcmp(a , b) ;//比较,若相同返回false
strcat(a , b) ;//连接(放到a中)

3.3 竞赛题目选讲

每一道例题都能学到很多知识。

例3-1:TeX中的引号

字符串的输入

作者共介绍了3种输入方法:

函数名称用法
fgetc(fin)读取打开的文件fin,返回一个int值,要去除EOF符
scanf("%s" , s)遇到空格、换行就会停下
str = getchar()需要特判EOF符
fgets(buf , maxn , fin)读取文件中的一行,最多读取maxn-1个字符,一个字符没读到就返回NULL

这里没有提到gets()因为他已经删去了。

三目运算符

a : b ? c表示
当条件a为真时执行b反之执行c
最好不要用。

例3-2 WERTYU

“重构字典新定义法”

这里讲述了一种新的算法,他类似于将答案提前写在一个常数数组中,便于我们输出或使用。有点类似于搜索算法中把x y值的增减提前封装到一个数组中,是打表法的低配版。
本题中作者直接将键盘的格式封装到了数组s之中,之后每次调用只需要找数组的前一位即可。
后边还会用到他的思想。

例3-3 回文词

又是一道“字典法”的题!
补充一下数组 msg[m*2+p]的含义是:
作者将数组分成了两个板块(就像是图书馆分成小说区、科普区…)m可以决定他是否是镜像类,当是镜像类时,m=1,此时直接去镜像区[2,3]去找答案。反之,m=0,去非镜像区找答案。而p决定着图书所在的排数。
综上就可以精准的定位答案的位置。

函数: isalpha()

isalpha() ;//检查是否为字母
isdigit() ;//检查是否为数字
isprint() ;//检查是否为可打印字符
toupper() ;//转大写
tolower() ;//转小写
//头文件:
#include<cctype>

例3-4 猜数字的提示

小心格式!!!!
每个数对前有空格!

例3-5 生成元

c++中 无穷大的表示方法为:

#define INF 0x3f3f3f3f

例3-6 环状序列

很好的模拟题。
输出字符(串):

putchar() ;

3.4 注解与习题

另发题解,请关注~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值