算法题笔记
就是做题遇到的问题,解决的思路;还有细节...
1 常见算法/数据结构
见 https://www.cnblogs.com/lqerio/p/13535931.html
2 STL
2.1 map
using namespace std;
typedef pair<int,int> info;
map<string,info> family = {{"Adam",make_pair(1,930)},{"Seth",make_pair(2,912)}}; /初始化
info p;
map<string,info> person;
p=make_pair(1,930); //p.first,p.second
person.insert(make_pair("Adam",p)); //插入 注意 make_pair
map<string,info>::iterator iter1; //迭代器
if(family.count(name1)>0) //map在find前要先count确定存在
iter1=family.find(name1); //find 返回迭代器
iter1->second.first==-1; //注意map的迭代器用-> 。 pair用.
iter->first iter->second;
2.2 pair
typedef pair<int,int> info; //这样做类型。
info p;
p=make_pair(1,930); //赋值
p.first,p.second //使用
2.3 queue
void clearque(queue<Node>& q){ //注意 &
queue<Node> empty;
swap(empty, q);
}
2.4 vector
注意map,vector,queue每次使用要清空(vec.clear,while(!empty)queue.pop)
不同于map(map有find方法),vector本身是没有find这一方法,其find是依靠algorithm来实现的。
vector<int>::iterator it = find(vec.begin(), vec.end(), 6);
if (it != vec.end())
cout<<*it<<endl;
else
cout<<"can not find"<<endl;
count 类似
2.5 string
string.length() .size()
bool cmp1(string a,string b){
return a<b;
}
vector<string>ans;
sort(ans.begin(),ans.end(),cmp1);
空string 用 “” 不能用''
string 不能==char,比如
string aa = "a";
if (aa[0] == 'a' ) 对 || aa == 'a' 错
cout << 1;
string.clear()
string.erase()
3 技巧
3.1 浮点数精度
设置eps=1e-9。fabs(a-b)<eps 则认为a==b。
fabs ,abs 在 cmath
3.2 结构体构造函数
struct node
{
int key;
int height;
int size; //tree node 个数
node *left, *right;
/*
node(int x) : key(x), height(1), size(1), left(NULL), right(NULL) {}
node() : key(NULL), height(NULL), size(NULL), left(NULL), right(NULL){}
*/
node(int k)
{
key = k;
height = 1;
size = 1;
left = right = 0;
}
};
struct node{
int data;
string str;
char x;
//自己写的初始化函数
void init(int a, string b, char c){
this->data = a;
this->str = b;
this->x = c;
}
node() :x(), str(), data(){}
node(int a, string b, char c) :x(c), str(b), data(a){}
}N[10];
N[1] = { 2,"c++",'d' }; //无参默认结构体构造体函数
N[2].init(3, "java", 'e'); //自定义初始化函数的调用
N[3] = node(4, "python", 'f'); //有参数结构体构造函数
3.3 new && 不定长数组
char* Data = new char[N]; // 不定长数组
int *a = new int[5];
delete []a; //释放int数组空间
3.4模运算
被除数÷除数=商……余数。
由此可知,余数=被除数-商×除数 (*)
以下摘录自C++ Primer(P130)
操作符%称为“求余”或“求模”操作符,该操作符的操作数只能为整型。
如果两个操作数为正,结果也为正;如果两个操作数都为负数,结果也为负数;如果一个操作数为正数,一个操作数为负数,求模结果的符号取决于机器。
当操作数中有一个为负,一个为正是,求模操作结果值的符号可依据分子(被除数)或分母(除数)的符号而定。
如果求模的结果随分子的符号,则除出来的值向零一侧取整;如果求模与分母的符号匹配,则除出来的值向负无穷大一侧取整。
取模运算https://baike.baidu.com/item/%E5%8F%96%E6%A8%A1%E8%BF%90%E7%AE%97/10739384?fr=aladdin
3.5 奇偶判断
len&1==1 奇数 (这里不能用亦或,想想就知道因为 &1 相当于& 000001)
3.6 数组开法
woj1019 ,因为输出 是按行,所以记录数组应该是[classnum][day]的形式
operator<
见c++ categories 下有一篇分析
struct problem{
int time,penalty;
bool operator <(const problem &tmp)const{
return penalty>tmp.penalty;
}
};
/* 多个大小比较时
if(a.grade != b.grade)
return a.grade < b.grade;
else if(t != 0)
return t < 0;
else
return a.age < b.age;
*/
4 常见错误
4.1 除0
比如a/b6,最好用a-6*b0
4.2 segment fault
https://blog.csdn.net/qq_36589706/article/details/81505221
char *c = "hello world";
c[1] = 'H';
char c[]="helloworld"; //前者c是地址,指向常量"hello world",不可修改
int i=0;
scanf ("%d", i); /* should have used &i */
printf ("%d\n", i);
return 0;
int *p = null;
*p = 1;
数组越界
printf("%s\n", b);
return 0; //整数当成地址,一直遇到0才停。
栈溢出
4.3 引用传递
引用导致修改,或者忘了引用没有修改。
4.4 数组大小开的不对
太大了溢出,太小了容易越界 (这主要是细节,比如woj 1006 200 0000 我写成 20000+5就segmenetfault了,这种错误我犯过很多次)
4.5 运算符优先级
// 主要是记得加括号,比如
tmp=(tmp>maxtri[j][i])?maxtri[j][i]:tmp; //注意加括号
4.6 double int
// 涉及浮点数注意 比较+eps (精度要求很高的时候)
(capacity[j][i]>maxcap&&cnt[j]>0){ //常见错误,直接==0(double a>b) 应该用eps。但是这里数据在100,精度没那么高直接用也行
//int double 注意*1.0
avg=((double)minh+maxh)/2; //注意double
4.7 语句位置
//常见错误 放错位置,注意语句在哪个结构({括号)
//;maxcap=capacity[j][i]; //常见错误 ij反了,注意意义!!。比如建图时先人再动物,然后遍历的时候先动物,ij就要反过来 见woj 1008
4.8 全局变量
不小心修改了全局变量导致出错
如woj1009,全局变量m为边数,但是spfa模板中addedge()里也有一个m,就改了。解决是修改addedge()中的m为edgenum
const int x=5; 不要 int x;
4.9 整数溢出
4.9.1 最后取模转到过程中
主要是连续+,*的溢出。一般题目告诉你最后取模,边计算边取模就好了
for(i=0;i<num-1;i++){
maxn=maxn*2;
maxn=maxn%2006; //防溢出
}
4.9.2 负数取模
模运算见 3.4
负数取模应该保证是正数才不会错
x=)=(x%mod+mod)%mod
4.10 数据类型选择
选择合适的double,int,longLong...同时输出注意对应,比如%lld
woj1012
ans用long long
4.11 C++ 标准库y1 变量声明为y1的问题
显示变量y1 和C++标准库中的某个变量名称冲突,这个问题应当引起注意。
另外这不是头文件写成<bits/stdc++.h>引起的,即使换成各具体的头文件(<iostream>, <algorithm>, <ctring>)还是会返回这个错误。
具体原因及解决办法还有待研究。
main.cpp:4:17:错误:'double y1'被重新声明为另一种符号
double x1,x2,x3,y1,y2,y3,z1,z2,z3;
^〜
在从/usr/include/features.h:424:0包含的文件,
从/usr/include/x86_64-linux-gnu/c++/7/bits/os_defines.h:39,
从/ usr /包括/ x86_64的-linux-gnu / c ++ / 7 / bits / c ++ config.h:533,
来自/ usr / include / c ++ / 7 / cstdio:41,
来自main.cpp:2:
/ usr / include / x86_64-linux- gnu / bits / mathcalls.h:221:1:注意:先前的声明'double y1(double)'
__MATHCALL(y1 ,,(_Mdouble_));
4.12 C 和C++ char数组赋值'\0'的问题
woj 1013
mapp[i][len]='\0'; //C可以这样,C++不行。 Array must be initialized with a brace enclosed initializer
mapp[i][len]=; c++还没找到解决办法。建议用string代替 可能是直接赋值被当成初始化了?
4.13 考虑不全
woj1019,课程名说有空格,没有说只有一个空格,要考虑多个空格
4.14 初始化/每次循环初始化(清零)
包括变量(数组)的初始化
每次循环把上次结果清零
queue,vector等的清空
5 其他函数
5.1 cctype
包含 isalpha,isdigit...
isalpha = s[0] >= 'a' && s[0] <= 'z') || (s[0] >= 'A' && s[0] <= 'Z')
5.2 memset
// memset(final,0,sizeof(int)*4); 注意memset是字节为单位,只能赋值0。比如int 4字节0000 0X01010101.
//速度慢 另外注意一个字节2个16进制数
// memset(a,0x3f,sizeof(a))
5.3 sqrt pow
<cmath>
sqrt return double
pow(a,b)a^b
5.4 abs fabs
cmath
对应整形浮点型
C语言中,
求整数的绝对值abs()和labs()应该包含stdlib.h
求浮点数的绝对值fabs()应该包含math.h
在C++中,只需要包括cmath即可。
5.5 sort qsort 推荐用sort
algorithm
sort 推荐,一般更快
sort(first_pointer,first_pointer+n,cmp) //sort(mapp,mapp+5,cmp) sort(vec.begin(),vec.end())
cmp bool返回
不推荐
cstdlib
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
base-- 指向要排序的数组的第一个元素的指针。
nitems-- 由 base 指向的数组中元素的个数。
size-- 数组中每个元素的大小,以字节为单位。
compar-- 用来比较两个元素的函数,即函数指针(回调函数).
cmp 用int返回,需要const void*
int compare(const void *a,const void *b)
{
return *(int*)b-*(int*)a;//从大到小排序,若从小到大牌组为:*(int*)a-*(int*)b
}
6.输入输出
6.1 scanf printf
scanf 函数是有返回值的,它的返回值可以分成三种情况
- 正整数,表示正确输入参数的个数。例如执行 scanf("%d %d", &a, &b);
如果用户输入"3 4",可以正确输入,返回2(正确输入了两个变量);
如果用户输入"3,4",可以正确输入a,无法输入b,返回1(正确输入了一个变量)。 - 0,表示用户的输入不匹配,无法正确输入任何值。如上例,用户如果输入",3 4",返回0。
- EOF,这是在stdio.h里面定义的常量(通常值为-1),表示输入流已经结束。
在Windows下,用户按下CTRL+Z(会看到一个^Z字符)再按下回车(可能需要重复2次),就表示输入结束;
Linux/Unix下使用CTRL+D表示输入结束。
本题(woj1007 feedind animals)可以使用下面的代码来处理输入:
while (scanf("%d", &n) == 1) / 或!= EOF , 但前者更好 /
woj1009 输入数字和字符,同时空格间隔
//这样写有问题。读了空格
scanf("%d%d%d%d%d",&from,&to,&power,&speed,&dist);
scanf("%c",&word);
scanf("%d%d%d%d%d",&from,&to,&power,&speed,&dist);
getchar();scanf("%c",&word);getchar(); //处理最后一个字符前的空格这样可以,但是麻烦
//推荐
scanf("%d %d %d %d %d %c",&from,&to,&power,&speed,&dist,&word); //注意%c不是%s 。也可以fstream
顺便说一下,printf的返回值是输出的字符数,例如,printf("1234")的返回值是4,而printf("1234\n")的返回值是5。
6.2 输入结束 EOF
1.while((scanf"%d,%d",&m,&n)==2)
2.while((scanf"%d,%d",&m,&n)!=EOF)
3.while(cin>>m>>n)
6.3 空格截断 getline
注意cin 空格截断,如果不想截断用getline。
//比如
string line; getline(cin,line);
istream& getline ( istream &is , string &str , char delim );
string line;
while(getline(cin,line,'#'))
cout <<line;
// You are the #best! 剩下的在缓冲区 EOF仍然可退出 然后#不会读入
//fflush(stdin);清空
6.4 缓冲区
fflush(stdin)
6.5 读题
// woj1009 题目说了每个测试有空行 所以 每个例子后面 getchar() 一下
6.6 float double int (数据类型)
float,单精度浮点型,对应%f.
double,双精度浮点型,对应%lf.
在用于输出时:
float类型可以使用%lf格式,但不会有任何好处。
double类型如果使用了%f格式可能会导致输出错误。
在用于输入时:
double 类型使用了%f格式,会导致输入值错误。
float类型使用double类型不仅会导致输入错误,还可能引起程序崩溃。
2^16 =65536
[-2^31,2^31),即-2147483648~2147483647约等于2e9,
7 数学知识
7.1 几何
7.1 三角
woj 1017
//余弦定理 cos A=(b²+c²-a²)/2bc
///正弦定理 a/sinA = b/sinB =c/sinC = 2r=D(r为外接圆半径,D为直径)
//圆周角定理 圆周角所对弧对应角为圆周角的二倍
//(海伦公式)(p=(a+b+c)/2)
//S=sqrt[p(p-a)(p-b)(p-c)]
// 三角形面积 1/2*b*c*sina
7.2 行列式(线性代数)
woj 1014
二阶三阶行列式求值可以用沙路法(对角线法则)
行列式就是线性变换的伸缩因子,
//原来的体积是1,经过矩阵的线性变换的体积就是1*矩阵行列式
8. 其它
一般认为计算机每秒 1e8条(做题还是当成1E7吧)简单语句,估计一下复杂度和量级可以估算自己的时间,一般百万级(不超过1000万比较好)。一般内存32/64MB。
参考资料:紫书等等见https://github.com/TouwaErioH/ACM/tree/master/%E6%95%99%E6%9D%90