算法竞赛入门经典第二版-刘汝佳

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;
}
上述代码首部定义了local符号。本机测试时使用重定向方式读写文件。如果比赛要求读写标准输入输出,在提交之前删除#define LOCAL即可。
如果比赛要求用文件输出,但禁止用重定向方式。
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,sizeofint)*k)
如果数组是double类型的,int改为double就行。

数组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;
上述代码的意思是在字符串中查找字符buff[i],strchr会抛出bool值。
常用strchr()函数验证字符串s是否包含一组字符中所有字符。

 

 

3.3竞赛题目选讲

例题3-1,程序3-5
if语句"表达式版"
a?b:c的含义是:当a为真时返回b值,否则返回c。

例题3-2

定义常量数组无须指明大小,编译器会计算。
char s[] = "任意字符串";。

例题3-3

ASCII码表中大写字母,小写字母和数字都是连续的。如果ch是大写字母,则ch-'A'就是它在字母表中的序号。
如果ch是数字,值ch-'0',就是这个数字的数值本身。

 

posted @ 2026-05-26 15:14  小跳蚤幺幺幺  阅读(2)  评论(0)    收藏  举报