蓝桥杯-洛谷刷题-day3(C++)
目录
1.忽略回车的字符串输入
i.getline()
ii.逐个字符的识别再输入
2.获取绝对值abs()
3.做题时的误区
4.多个变量的某一个到达判断条件
i.max()
5.[NOIP2016 提高组] 玩具谜题
i.代码
6.逻辑上的圆圈
i.有限个数n的数组
7.数组的定义
i.动态数组
1.忽略回车的字符串输入
i.getline()
借助getline()函数,通过一定的操作可以实现忽略回车的输入,
string a;
string line;
while (getline(cin, line))
a += line;
cout << a << endl;
拓:在此循环中,输入ctrl + Z,getline会返回false.
ii.逐个字符的识别再输入
string a;
char tmp;
while (1) {
cin >> tmp;
if (终止条件,如tmp == '0') break;
else a += tmp;
}
2.获取绝对值abs()
#include<cmath>
cout << abs(2-3);
3.做题时的误区
i.
当题目需要 ABC的输入,并指出输入D即为终止时,并不代表可以直接
if(ch == 'D')break;
else str += ch;
题目检测时给予的输入不只有ABCD.
ii.
函数的重复度,会影响评判。
4.多个变量的某一个到达判断条件
i.max()
如,a,b只要有一个到达21,之后就要进行别的操作,使用(max(a, b) >= 21),明显比用((a == 21) || (b == 21))要ok很多。
5.[NOIP2016 提高组] 玩具谜题
i.代码
#include <iostream>
#include <iomanip> //操纵器,个位数字,多位输出;保留n位小数输出
#include <cmath> //向上取整函数ceil
#include <string>
using namespace std;
//人
class Man
{
public:
//朝向
int direction;
//职称
string name;
void setMan(int di, string na)
{
direction = di;
name = na;
}
};
//命令
class Command
{
public:
//左右
int lefOrRi;
//步数
int number;
void setCommand(int leR, int num)
{
lefOrRi = leR;
number = num;
}
};
void CheckMan(Man* man, Command* com, int n, int m)
{
//man以逆时针站好,0朝里,左递减,右递增;1朝外,左递增,右递减。
//左为0,右为1
int p = 0;//指向当前的Man
for (int i = 0; i < m; i++)
{
//先看命令的左右,再看圈里的朝向,p是man的下标,i是com的下标
if (com[i].lefOrRi == 0)
{
if (man[p].direction == 0)
{
//优化的点,排除循环的冗长,一步到位
p = p - com[i].number;
if (p < 0)
p = n + p;
}
else if (man[p].direction == 1)
{
//while (com[i].number--)
//p = (p + 1) % n;
p = (p + com[i].number) % n;
}
}
//命令朝右
else if (com[i].lefOrRi == 1)
{
//朝里
if (man[p].direction == 0)
{
/*while (com[i].number--)
{
p = (p + 1) % n;
}*/
p = (p + com[i].number) % n;
}
else if (man[p].direction == 1)
{
/*while (com[i].number--)
{
p--;
if (p < 0)
p = n + p;
}*/
p = p - com[i].number;
if (p < 0)
p = n + p;
}
}
}
cout << man[p].name;
}
void testlan()
{
//人数n,指令数m
int n = 0, m = 0;
cin >> n >> m;
//短暂存储方向和职业,指令左右和个数
int di;
string na;
int leR, num;
//建立人物序列,指令序列
//Man man[n];常规数组定义,其大小,在编译阶段就是已知的需要动态分配内存。
Man* man = new Man[n];
for (int i = 0; i < n; i++)
{
cin >> di >> na;
man[i].setMan(di, na);
}
Command* com = new Command[m];
for (int i = 0; i < m; i++)
{
cin >> leR >> num;
com[i].setCommand(leR, num);
}
CheckMan(man, com, n, m);
}
int main()
{
testlan();
return 0;
}
以下6.7,总结了一些要点。
6.逻辑上的圆圈
i.有限个数n的数组
p = (p + number) % n;
//p指示数组下标
//number指示移动的步数
//通过取余,可以实现,将在储存结构上的直线前进,等效为在逻辑上的转圈。
以上是加法的(这其实是数据结构,栈与队列部分的知识点),当然就有减法的情况,
p = p - number;
if (p < 0)
p = n + p;
可优化为
p = (p - number + n) % n;
这没什么好说的。
7.数组的定义
i.动态数组
int n;
cin >> n;
int a[n];
上文代码会报错,这种常规数组定义在编译阶段就完成了创建(上文数组大小需要在运行阶段才能确定,这是矛盾的), [] 内只能是常数。
要实现上文这种,在运行后确立数组大小的形式,就是建立动态数组。
· 法一----使用vector
int n;
cin >> n;
vector<int> a(n);
· 法二----new关键字(不如法一安全)
int* a = new int[n];
delete[] a;