算法竞赛入门经典_学习笔记_各例题和训练源文件
第01章_程序设计入门
Example_0108_变量交换_方法1_三变量法.cpp
Example_0109_变量交换_方法2_不借助第三变量.cpp
Example_0111_鸡兔同笼_数学二元一次方程.cpp
Example_0113_三整数排序_逐情况列举法.cpp
Example_0114_三整数排序_比较交换法.cpp
Example_0115_三整数排序_最值计算法.cpp
Exercise_0101_平均数(average)_CPP版.cpp
Exercise_0101_平均数(average)_C语言版.cpp
Exercise_0102_温度(temperature).cpp
Exercise_0103_连续和(sum).cpp
Exercise_0104_正弦和余弦(sincos).cpp
Exercise_0105_距离(distance).cpp
Exercise_0106_偶数(odd)_利用整型数据法.cpp
Exercise_0106_偶数(odd)_求余运算法.cpp
Exercise_0107_打折(discount).cpp
Exercise_0108_绝对值(abs).cpp
Exercise_0109_三角形(triangle).cpp
Exercise_0110_闰年(leapYear).cpp
Thinking_0101_计算int型整数的最小值和最大值.cpp
// Example_0108_变量交换_方法1_三变量法.cpp
/**
* 交换变量的第一种经典方法:
* 通过多申请一个变量,然后临时存储,交换。
* 这种方法可以理解成:刚刚被临时存储值的变量,可以被赋值。
* 如:刚刚 t = a; 那么此时的变量a已经被临时变量保存了,那么就可以进行变化了。
* 现在的目标是将a与b交换,即然现在a可以变化,那就可以直接存放b的值。
* 最后,即然b的值已经被拿过去了,为达交换目的,现在a的值可以从t那么取回放到b处了。
**/
#include <iostream>
int main()
{
int a, b, t;
std::cin >> a >> b;
t = a; // 开始交换
a = b;
b = t; // 交换完毕
std::cout << a << b << std::endl;
return 0;
}
// Example_0109_变量交换_方法2_不借助第三变量.cpp
/**
* 交换变量的第二种经典方法:不用借助第三变量就可以实现两值交换了。
* 注意:这方法不推介,因为适用范围比较窄,只有定义了加减法数据类型才可这样做。
* 这种方法可以理解成:相加得总量,相减换变量,总量再得分量;
* 开始交换:
* 第一步: a = a + b;
* 此时,将a变量变为原来两变量的总和;
* 第二步: b = a - b;
* 记住,此时的a,已是总和,那么总和减去原来的b的值,得到的就是原来的a的值,
* 所以在这一步当中,已经实现了将原a值赋值到b变量中。
* 第三步: a = a - b;
* 此时,右边的a仍是总和,右边的b的值已是原来的a值,所以要将a变量变为原来的b值,
* 只需要将总和减去原a值就得出原b值了,这一步,实现了将a变量的值变为b变量。
**/
#include <iostream>
int main()
{
int a, b;
std::cin >> a >> b;
a = a + b; // 开始交换
b = a - b;
a = a - b; // 交换完毕
std::cout << a << b << std::endl;
return 0;
}
// Example_0111_鸡兔同笼_数学二元一次方程.cpp
/**
* 题目名称:鸡兔同笼
* 题目描述:
* 已知鸡和兔的总数量为n,总腿数为m。输入n和m依次输出鸡的数目和兔的数目。
* 如果无解,则输出“No answer”(不要引号)。
* 样例输入: 14 32
* 样例输出: 12 2
* 样例输入: 10 16
* 样例输出: No answer
**/
/**
* 题目分析:
* 此题可以理解为解二元一次方程的数学题,鸡的数目为a, 兔的数目为b。
* 则: 4*b+2*a= m, a+b=n,解得:a=(4n-m)/2, b=n-a.
* 此外:考虑无解的情况,1:总腿数需要满足为偶数,2:鸡兔数目为正数。
**/
#include <iostream>
int main()
{
int n, m;
while(std::cin >> n >> m)
{
int a, b;
a = (4 * n - m) / 2;
b = n - a;
if (m % 2 != 0 || a < 0 || b < 0)
{
std::cout << "No answer\n";
continue;
}
else
{
std::cout << a << " " << b << std::endl;
}
}
return 0;
}
// Example_0113_三整数排序_逐情况列举法.cpp
/**
* 题目名称:三整数排序
* 题目描述:输入3个整数,从小到大排序后输出。
* 样例输入:26 78 12
* 样例输出:12 26 78
**/
/**
* 排序方法,逐情况列举,这种方法有点笨,不过也是很容易想出的方法。
* 如果有三个整数,那么,它就会有3*2*1+1种情况,
* 第一个数可取3种情况,最大,最小,中等。
* 那么第二个数就是,剩下的2种情况。
* 第三个数,没有其它可选,剩下1种情况。
**/
#include <stdio.h>
int main()
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
if (a <= b && b <= c) printf("%d %d %d\n", a, b, c);
else if(a <= c && c <= b) printf("%d %d %d\n", a, c, b);
else if(b <= c && c <= a) printf("%d %d %d\n", b, c, a);
else if(b <= a && a <= c) printf("%d %d %d\n", b, a, c);
else if(c <= a && a <= b) printf("%d %d %d\n", c, a, b);
else if(c <= b && b <= a) printf("%d %d %d\n", c, b, a);
return 0;
}
// Example_0114_三整数排序_比较交换法.cpp
/**
* 题目名称:三整数排序
* 题目描述:输入3个整数,从小到大排序后输出。
* 样例输入:26 78 12
* 样例输出:12 26 78
**/
/**
* 排序方法,比较交换法。
* 这种方法,将会改变原变量的数值,同时,在交换时,也用到了三变量法。
* 这里的比较只需要三次,第一次是将第一个数与第二个数比较,将较小值(交换)移到第一个数上。
* 第二次是将第一个数与第三个数比较,将较小值(交换)移到第一个数上,这样一来,第一个数就是最小值了。
* 接下来就只剩下两个需要确定的数,再将第二个数与第三个数进行比较,将较小值移至第二个数上(交换)。
* 此时,已完成了三数的排序,总思路是,先确定最小值,然后确定较小值,最后确定最大值。
**/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
int a, b, c, t;
cin >> a >> b >> c;
if (a > b) { t = a; a = b; b = t;}
if (a > c) { t = a; a = b; b = t;}
if (b > c) { t = a; a = b; b = t;}
cout << a << " " << b << " " << c << endl;
return 0;
}
// Example_0115_三整数排序_最值计算法.cpp
/**
* 题目名称:三整数排序
* 题目描述:输入3个整数,从小到大排序后输出。
* 样例输入:26 78 12
* 样例输出:12 26 78
**/
/**
* 排序方法,最值计算法。
* 这种方法,主要思路,筛选最大值和最小值,然后,得出中间值,最后,直接输出。
* 借用的变量可能比较多,三个。
* 首先,使用第一个变量作标记(记录),通过逐个比较,得出最大值;
* 然后,使用第二个变量作标记(记录),通过逐个比较,得出最小值;
* 最后,由总数值减去两最值,就可得到中值了。
**/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
int a, b, c;
int max, min, mid;
cin >> a >> b >> c;
max = a;
min = a;
if (b > max) max = b;
if (c > max) max = c;
if (b < min) min = b;
if (c < min) min = c;
mid = a + b + c - max - min;
cout << max << " " << mid << " " << min << endl;
return 0;
}
// Exercise_0101_平均数(average)_CPP版.cpp
/**
* 题目要求:输入3个整数,输出它们的平均值,保留3位小数。
**/
#include <iostream>
using std::cin;
using std::cout;
int main()
{
double a, b, c;
cin >> a >> b >> c;
cout.precision(3); // 此句将对以后的cout语句都有效,默认情况下会输出六位小数
cout << (a + b + c) / 3 << std::endl;
system("pause");
return 0;
}
// Exercise_0101_平均数(average)_C语言版.cpp
/**
* 题目要求:输入3个整数,输出它们的平均值,保留3位小数。
**/
#include <stdio.h>
int main()
{
double a, b, c;
// 注意: lf代表double
scanf("%lf%lf%lf", &a, &b, &c);
double result = (a + b + c) / 3;
printf("%-.3lf\n", result);
return 0;
}
// Exercise_0102_温度(temperature).cpp
/**
* 题目要求:输入华氏温度f,输出对应的摄氏温度c,保留3位小数。
* 提示:c = 5 * (f - 32) / 9;
**/
#include <iostream>
using std::cin;
using std::cout;
int main()
{
double f;
cin >> f;
cout.precision(3);
cout << 5 * (f - 32) / 9 << std::endl;
return 0;
}
// Exercise_0103_连续和(sum).cpp
/**
* 题目要求:输入正整数n,输出 1+2+...+n的值。
**/
#include <iostream>
using std::cin;
using std::cout;
int main()
{
long n;
cin >> n;
long s = 0;
++n;
for ( int i = 1; i < n; ++i)
{
s += i;
}
cout << s << std::endl;
return 0;
}
// Exercise_0104_正弦和余弦(sincos).cpp
/**
* 题目要求:输入正整数n(n<360),输出n度的正弦、余弦函数值。
* 提示:可使用数学函数。
**/
#include <iostream>
#include <cmath>
using std::cin;
using std::cout;
int main()
{
double n;
cin >> n;
cout << sin(n) << " " << cos(n) << std::endl;
return 0;
}
// Exercise_0105_距离(distance).cpp
/**
* 题目要求:输入4个浮点数x1, y1, x2, y2, 输出平面坐标系中点(x1, y1)到点(x2, y2)的距离。
**/
#include <iostream>
#include <cmath>
using std::cin;
using std::cout;
int main()
{
float x1, x2, y1, y2;
cin >> x1 >> y1 >> x2 >> y2;
// abs求绝对值
// pow求次方
// sqrt开平方
cout << sqrt(pow(abs(x1 - x2), 2) + pow(abs(y1 - y2), 2)) << std::endl;
return 0;
}
// Exercise_0106_偶数(odd)_利用整型数据法.cpp
/**
* 题目要求:输入一个整数,判断它是否为偶数。
* 如果是,则输出“yes”,否则输出“no”。
* 提示:可用多种方法判断。
**/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
int number;
cin >> number;
// 若非偶数,则除以2时会失真,再乘以2时则不会等于本身
if (number / 2 * 2 == number){
cout << "yes" << endl;
}
else{
cout << "no" << endl;
}
return 0;
}
// Exercise_0106_偶数(odd)_求余运算法.cpp
/**
* 题目要求:输入一个整数,判断它是否为偶数。
* 如果是,则输出“yes”,否则输出“no”。
* 提示:可用多种方法判断。
**/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
int number;
cin >> number;
// 若为偶数,则除以2时无余数
if (number % 2 == 0){
cout << "yes" << endl;
}
else{
cout << "no" << endl;
}
return 0;
}
// Exercise_0107_打折(discount).cpp
/**
* 题目要求:一件衣服95元,若消费满300元,可打八五折。
* 输入购买衣服件数,输出需要支付的金额(单位:元),保留两位小数。
**/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
const double discount = 0.85;
const double minConsume = 300.0;
const double singleConsume = 95.0;
double number;
cin >> number;
double sum = number * singleConsume;
if (minConsume < sum){
sum *= discount;
}
cout.precision(2);
cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
cout << sum << endl;
return 0;
}
// Exercise_0108_绝对值(abs).cpp
/**
* 题目要求:输入一个浮点数,输出它的绝对值,保留两位小数。
* 不能使用库函数math或cmath
**/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
float number;
cin >> number;
if (0 > number){
number = 0 - number;
}
cout << number << endl;
return 0;
}
// Exercise_0109_三角形(triangle).cpp
/**
* 题目要求:输入三角形三边长度值(均为正整数),判断它是否能为直角三角形的三个边长。
* 如果可以,则输出“yes”,如果不能,则输出“no”。
* 如果根本无法构成三角形,则输出“not a triangle”。
**/
/**
* 题目分析:
* 对于这题,可以先判断是否三角形,然后再进行下一步的判断,判断是否能构成直接三角形。
* 判断三角形:两边之和大于第三边即可判断。
* 判断是否直角三角形:可以用勾股定理,不过前提得先判断出最大边是哪一条。
**/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
long a, b, c;
cin >> a >> b >> c;
// 下面开始判断是否能成为三角形
if (a + b < c || a + c < b || b + c < a){
cout << "not a triangle" << endl;
return 0;
}
// 下面先找出最大边,并将最大边交换放到变量a处存放
long max = a;
if (max < b){max = b; b = a; a = max;}
if (max < c){max = c; c = a; a = max;}
// 下面开始使用勾股定理判断是否能成为直角三角形
if (a * a == b * b + c * c){
cout << "yes" << endl;
}
else{
cout << "no" << endl;
}
return 0;
}
// Exercise_0110_闰年(leapYear).cpp
/**
* 题目要求:输入年份,判断是否闰年。
* 如果是,则输出“yes”,否则输出“no”。
**/
/**
* 题目分析:首先得知道常识是:平年365天,闰年366天。
* 计算方法:公历闰年的精确计算方法(按一回归年365天5小时48分45.5秒)
* ① 普通年能被4整除且不能被100整除的为闰年。(如2004年就是闰年,1901年不是闰年)
* ② 世纪年能被400整除的是闰年。(如2000年是闰年,1900年不是闰年)
* ③ 对于数值很大的年份,这年如果能整除3200,并且能整除172800则是闰年。
* 如172800年是闰年,86400年不是闰年(因为虽然能整除3200,但不能整除172800)(此按一回归年365天5h48'45.5''计算)。
* 程序编写思路:从大到小判断。
* ① 先判断数值是否满足第3个条件(数值很大的年份),因为这样判断可以先满足大的数值的条件,避免小数值条件的多余判断。
* ② 再判断数值是否满足第2个条件(世纪年),判断是否闰年。
* ③ 最后使用普通年的判断方法以判断是否闰年。
**/
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int main()
{
long year;
cin >> year;
// 数值很大的年份
if ( year > 172800){
if (0 == year % 3200){
cout << "yes" << endl;
}
else{
cout << "no" << endl;
}
}
// 世纪年
else if(0 == year % 100){
if(0 == year % 400){
cout << "yes" << endl;
}
else{
cout << "no" << endl;
}
}
// 普通年
else{
if (0 == year % 4){
cout << "yes" << endl;
}
else{
cout << "no" << endl;
}
}
return 0;
}
// Thinking_0101_计算int型整数的最小值和最大值.cpp
/**
* 计算方法:
* 最小值:当int型的数据到了最小值时,然后再减1(即越界时),它会变成正数,
* 如果此时再将此数值加1,就可以知道这最小值是多少了。
* 最大值:同理,当int型的数据到了最大值时,然后再加1(即越界时),它会变成负数,
* 如果此时再将此数值减1,就可以知道这最大值是多少了。
**/
#include <iostream>
int int_min()
{
int n = 0;
while(0 >= n)
{
--n;
}
++n;
return n;
}
int int_max()
{
int n = 0;
while(n >= 0)
{
++n;
}
--n;
return n;
}
int main()
{
int min = int_min();
int max = int_max();
std::cout << min << " " << max << std::endl;
system("pause");
return 0;
}