算法题笔记

就是做题遇到的问题,解决的思路;还有细节...

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 函数是有返回值的,它的返回值可以分成三种情况

  1. 正整数,表示正确输入参数的个数。例如执行 scanf("%d %d", &a, &b);
    如果用户输入"3 4",可以正确输入,返回2(正确输入了两个变量);
    如果用户输入"3,4",可以正确输入a,无法输入b,返回1(正确输入了一个变量)。
  2. 0,表示用户的输入不匹配,无法正确输入任何值。如上例,用户如果输入",3 4",返回0。
  3. 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

posted @ 2020-08-11 21:06  Erio  阅读(289)  评论(0编辑  收藏  举报