算法竞赛入门经典第二版-刘汝佳
1.语言篇
1.程序设计入门
1.1算术表达式
整数值用%d输出,实数用%f输出。只要运算符的两边都是整数,则运算结果也会是整数。8/5的值是1,而不是1.6。8.0和5.0被看作是实数或浮点数,浮点数之间的运算结果是浮点数。
1.3顺序结构程序设计
算法竞赛是在比谁能更好地解决问题,而不是在比谁写的程序更高级。
第2章循环程序结构设计
2.1for循环
函数floor(x)返回不超过x的最大整数。四舍五入:floor(x+0.5)。
取正整数各个位上数的方法:a为两位正整数,a的十位是a/10,a的个位是a%10。
2.2 While循环和do while循环
循环次数不确定,或非递增式循环,适合while循环来实现。
先计算再判断,循环终止判断在计算之后,适合用do while循环。
int整数的大小:
-2^31~2^31-1。
2^31 = 2147483647。10位。
10^9只比2^31小一点,当数据取到最大10^9做一些乘法运算数据就会溢出。
long long数值型大小:
-2^63~2^63-1。输入格式为:%lld。
C语言中10^-6表示:1e-6。
2.3循环的代价
time.h头文件, Clock()函数返回程序目前为止运行的时间。该时间除以常数CLOCKS_PER_SEC得到以秒为单位的时间。
键盘输入的时间也会被计算在内。命令行下执行echo 20 | abc。操作系统会自动把20输入,其中abc是程序名。
--这个东西要在cmd中进入到abc.exe才行,好像不是很实用。
2.4 算法竞赛中的输入输出框架
输入次数不确定的输入语句://输入一些整数,输入一些整数,求出它们的最小值、最大值和平均值(保留3位小数)。
while(scanf("%d", &x) == 1) {};
用上述方式输入,Windows下输入完毕后按enter键,再按ctrl+z键,最后再按enter键即可结束输入。
如果读入的是整数,求平均要输出浮点数,不必声明一个浮点类型变量,计算sum/n强制转换成浮点类型就行。
(double)s / n
输入包含多组数据,每组数据第一行是整数个数n,第二行是n个整数。n=0为输入结束
标记,程序应当忽略这组数据。相邻两组数据之间应输出一个空行。这样的格式在算法竞赛中非常常见。
int x, n = 0, s = 0, max = -INF, min = INF, kase = 0; while (scanf("%d", &n) == 1 && n) {};
每组数据有多个变量while中的scanf有改动,几个变量就是scanf() == 几。
while (scanf("%lld %lld", &n, &m) == 2 && n && m)
#define INF 1000000后面不要加分号:
#include<stdio.h>
#define INF 1000000000
每次测试要手动输入许多数。一个好的方法,用文件把输入数据保存在文件中,输出数据也保存在文件中。
使用文件最简单的方法是使用输入输出重定向。在main函数入口加入以下两条语句,main函数进入后的前两行。
feropen(" input.txt", "r", stdin);
feropen(" output.txt", "w", stdout);
上述语句使得scanf从文件input.txt读入,printf写入文件output.txt。所有读键盘输入,写屏幕输出的函数都将改用文件。
本机测试使用文件重定向,提交到比赛就自动删除重定向语句。
#define LOCAL #include<stdio.h> int main() { #ifdef LOACL feropen(" input.txt", "r", stdin); feropen(" output.txt", "w", stdout); #endif // 功能语句 return 0; }
如果比赛要求用文件输出,但禁止用重定向方式。
int main() { FILE *fin, *fout; fin=fopen("data.in", "rd"); fout=fopen("data.out", "wd"); //--变量声明; while(scanf(fin, "%d", &x)==1) {}; fprintf(fout, "输出数据格式", 输出变量表列); fclose(fin); fclose(fout); return 0; }
截尾:
最后一位小数不四舍五入,进行截尾处理。保留c位小数截尾,公式:
res = floor( 数值 * 10^c ) / 10^c
指定精确到小数点后c位输出控制符:
//输出保留小数点后几数由输入c决定 printf("%.*f\n", c);
第3章数组和字符串
3.1数组
在main函数的外面声明数组时才可以开得很大。在main函数内,声明大数组就会异常退出。
比较大的数组应尽量声明在main函数外,否则程序可能无法运行。
复制数组元素到另外一个数组
从数组a复制k个元素到数组b,a,b都是整型数组:
memcpy(b,a,sizeof(int)*k)
数组a全部复制到b中:
memcpy(b,a,sizeof(a))
3-3蛇形数组
最外层while循环下标变量要小于n*n,里面四个while,判断条件为下一步的下标是否越界和下一步的元素是否被填充。
赋值后立刻作为数组下标是可以的:
a[x = 0][y = n - 1] = 1;
3.2字符数组
scanf("%s", s)会读入一个不含空格、tab和回车符的字符串,存入字符数组s。
程序3-4竖式问题
如果用拆解整数的方式来做这个题不知道会有多难了,用sprintf()函数把数字全部输出到字符数组,再用strchr来进行字符查找,就快很多了。
sprintf()函数
sprintf()函数把信息输出到字符串。用法:
//buf是char型数组char buf[99] sprintf(buf, "%d%d%d%d%d", abc, de, x, y, z);
strchr()函数的作用是在一个字符串中查找单个字符。
if(strchr(s, buf[i]) == null) ok = 0;
常用strchr()函数验证字符串s是否包含一组字符中所有字符。
3.3竞赛题目选讲
例题3-1,程序3-5if语句"表达式版"
a?b:c的含义是:当a为真时返回b值,否则返回c。
例题3-2
定义常量数组无须指明大小,编译器会计算。char s[] = "任意字符串";。
例题3-3
ASCII码表中大写字母,小写字母和数字都是连续的。如果ch是大写字母,则ch-'A'就是它在字母表中的序号。如果ch是数字,值ch-'0',就是这个数字的数值本身。

浙公网安备 33010602011771号