开学第一次总结

目录

一:C++零散知识

二:STL:具体语法不写了,网上多的是,这里链接是凌乱之风大佬的总结

1:vector:

2:set

3:map :

4:queue

5:priority_queue:

6:stack

7:Pair

8: next_permutation

三:数学入门

1:快速幂

2:欧几里得算法 

四:DFS

1:DFS

 五:综述


一:C++零散知识

1:cout输出小数点位数:

//头文件加入#include <iomanip>
#include<iostream>
#include<iomanip>
using namespace std;
const float pi = 3.1415926;
int main()
{

    cout.setf(ios::fixed);
    cout<<fixed<<setprecision(9)<<pi<<endl;//以固定位数显示
    cout.unsetf(ios::fixed);
    cout<<setprecision(9)<<pi<<endl;//以是几位数输出
    return 0;
}

2:cout关闭同步

std::ios::sync_with_stdio(false);

3:putchar()吸收空格很有用

4:冒泡排序我最喜欢,但经常超时,快速排序比冒泡快。

二:STL:具体语法不写了,网上多的是,这里链接是凌乱之风大佬的总结

STL常用容器总结_凌乱之风的博客-CSDN博客

个人感觉Acm就是C语言+STL,学会使用STL非常重要

STL对程序简化非常重要

1:vector:

vector相比于其他动态序列容器,访问元素时更加高效,在末尾添加或者删除元素时,更加高效,但是如果不在末尾添加或者删除元素,效率更低。

vector经常用作数组使用,再不确定元素个数时能够很好的节省空间,在一些题目中,需要把不确定个数的数据输出在同一行,中间用空格隔开,这时用vector先记录再一次性输出比较方便。

vector声明和初始化中,可以用数组元素初始化vector,也可以部分初始化,比较灵活,

vector在内存中,就像二维数组一样,是一个连续的数组,在C++11中,可以返回一个指针指向这个数组 int*p = vec.data();

vector中的元素可以像普通的数组那样用cin>>;cout<<a[i]一样输入输出,也可以用迭代器进行输出vector<int>::iterator迭代器比较灵活,不但可以表示元素位置,还可以在容器中前后移动。除此之外,vector还能使用指针形式间接访问

#include<iostream>
#include<vector>
using namespace std ;

int main()
    {
        vector<int> a(10, 1) ;
for(int i = 0;i<10;i++)
{
    cin>>a[i];
}
vector<int>::iterator t ;
for(t=a.begin(); t!=a.end(); t++)
{
        cout<<*t<<" " ;
}
        return 0 ;
    }

vector可以增加维数,但是维数多了就难以灵活控制。

vector< vector<int> > b(10, vector<int>(5)); 

同时vector可以实现邻接表建图 

应用:SDUT OnlineJudge

 山东理工大学OJ3 广度优先搜索练习之神奇的电梯 就可以使用vector建图,然后用BFS搜索;

#include<bits/stdc++.h>
using namespace std;
int bfs(int i, int as);
class node
{
public:
    int num;
    int step;
};
vector<int>pho[300];
int arr[300];
int n, m, q;
int main()
{
    int num, pos, to;
    while (cin >> n >> m >> q)
    {
        for (int i = 0; i < 205; i++) 
            pho[i].clear();
        for (int i = 0; i < m; i++)
        {
            cin >> pos >> num;
            while (num--)
            {
                cin >> to;
                pho[pos].push_back(to); 
            }
        }
        int as;
        while (q--)
        {
            cin >> as;
            memset(arr, 0, sizeof(arr));
            cout << bfs(1, as) << endl;
        }
    }
    return 0;
}
int bfs(int i, int as)
{
    arr[i] = 1;
    node p = {i, 1};
    queue<node> q;
    q.push(p);
    while (!q.empty())
    {
        node temp = q.front();
        q.pop();
        if (temp.num == as)
            return temp.step;

        vector<int>::iterator it;
        for (it = pho[temp.num].begin(); it < pho[temp.num].end(); it++)
        {
            node t = {*it, temp.step + 1};
            if (!arr[*it])
            {
                arr[*it] = 1;
                q.push(t);
            }
        }
    }
    return -1;
}

2:set

无序且不能重复,set封装了很多复杂的数据结构算法和数据结构操作,定义和写法和大部分STL差不太多,set访问只可以使用迭代器访问,主要是用来去重并按升序排序。

应用举例:SDUTOJ Message Flood

SDUT OnlineJudge

这道题非常典型,因为不用STL用其他排序都会超时

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m,i,j,len;
    char s[30];
    while(scanf("%d",&n)!=EOF&&n)
    {
        set<string>name;
        set<string>::iterator it;
        scanf("%d",&m);
        getchar();
        for(i=0; i<n; i++)
        {
            gets(s);
            len=strlen(s);
            for(j=0; j<len; j++)
            {
                s[j]=towlower(s[j]);
            }
            name.insert(s);
        }
        for(i=0; i<m; i++)
        {
            gets(s);
            len=strlen(s);
            for(j=0; j<len; j++)
            {
                s[j]=towlower(s[j]);
            }
            if(name.count(s))
                name.erase(s);
        }
        printf("%d\n",name.size());
    }
    return 0;
}

3:map :

map定义和其他STL容器不一样,有尖括号内有两个类型变量,map访问方式也有下表和迭代器访问,map和set都是使用红黑树实现,在建立映射过程中都会事先从小到大排序功能,C++11中增加了undordered_map,不按key排序只按键排序,速度比map快。

map用指针会出错,一般不用。python的map比c++的map去重快,因为python是hash map.

我对map的理解是,map大致相当于一个二维数组,或者是两个一维数组

示例:SDUT OJ Message Flood

SDUT OnlineJudge

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,m;
    int i,j;
    while (cin>>n&&n!=0)
    {
        cin>>m;
        map<string,int>mp;
        string s;
        for (i=1; i<=n; i++)
        {
            cin>>s;
            for (j=0; j<s.size(); j++)
            {
                s[j]=towlower(s[j]);
            }
            mp[s]++;
        }
        for (i=1; i<=m; i++)
        {
            cin>>s;
            for (j=0; j<s.size(); j++)
            {
                s[j]=towlower(s[j]);
            }
            mp.erase(s);
        }
        cout<<mp.size()<<endl;
    }
    return 0;
}

4:queue

初始化时必须要有数据类型,容器可省略,省略时则默认为deque 类型,queue是先进先出的容器,在实现广度优先搜索时,可以不用自己手动实现一个队列,使用queue作为代替可以提高程序的准确性,在使用front()和pop()函数前,必须用empty()判断队列是否为空。

注意:不能用vector容器初始化queue

因为queue转换器要求容器支持front()、back()、push_back()及 pop_front(),说明queue的数据从容器后端入栈而从前端出栈。所以可以使用deque和list对queue初始化,而vector因其缺少pop_front(),不能用于queue。

应用:SDUT OJ 2087 离散事件模拟-银行管理

SDUT OnlineJudge

我没写出这个题来 但我知道是队列

5:priority_queue:

优先队列,队首元素一定是优先级最高的那一个,可以以用来解决一些贪心难问题

6:stack

一个先进后出的容器;只能够用top()来访问栈顶的元素,stack一般用来模拟实现一些递归操作,用栈模拟递归造作可以避免递归层数过深导致程序崩溃。

在使用pop()top()函数之前必须先使用empty()函数判断栈是否为空。

应用:

SDUT OJ  数据结构实验之栈与队列八:栈的基本操作

SDUT OnlineJudge

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t,m,n;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&m,&n);
        stack<int>s;
        char x;
        int a,top=1;
        while(n--){
            printf("%s",x);
            if(x=='A'){
                if(s.empty()) cout <<"E"<<endl;
                else cout <<s.top()<<endl;
            }
            else if(x=='O'){
                if(s.empty()) cout <<"E"<<endl;
                else {cout <<s.top()<<endl;s.pop();top--;}
            }
            else{
                cin>>a;
                if(top<=m) {s.push(a);top++;}
                else cout <<"F"<<endl;
            }
        }
        if(t!=0) cout <<endl;
    }
    return 0;
}

7:Pair

和map比较类似 map像是一个个Pair组合而成,简单而有用,一般是和map一起使用

例题: sdut oj 众数问题

SDUT OnlineJudge

#include<bits/stdc++.h>
using namespace std;
const pair<int,int> a;
const pair<int,int> b;
bool cmp(pair<int,int> a,pair<int,int> b);
int main()
{
    int m,n;
    map<int,int>k;
    cin>>m;
    for(int i=0; i<m; i++)
    {
        scanf("%d",&n);
        k[n]++;
    }
    map<int,int>::iterator it = max_element(k.begin(),k.end(),cmp);
    cout<<it->first<<endl<<it->second<<endl;
    return 0;
}
bool cmp(pair<int,int>a,pair<int,int>b)
{
    return a.second<b.second;
}

8: next_permutation

next_permutation(first, last) 用于求序列[first,last)元素全排列中一个排序的下一个排序

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int a[3] = {0, 1, 2};
    do
    {
        for (int i = 0; i < 3; i++)
            cout<<a[i]<<' ';
        cout<<endl;
    }
    while (next_permutation(a, a + 3));
    return 0;
}

三:数学入门

1:快速幂

求a^b mod m 的值。

把b进行二进制分解。

void quick_pow(int a,int b)
{
    int ret = 1;
    while(b)
{
    if(b&1)ret = ret*a%mod;
        b>>=1;
        a=a*a%mod;
}
    return ret;
}

2:欧几里得算法 

就是求 gcd(x,y) d|x , d|y等价于d|(x-y),d|x 所以gcd(x,y)=gcd(x-y,y)=gcd(y,x%y) 显然每次取模后数字的大小至少折半(可以想一想为什么),所以复杂度是低于O(log max(x,y))级别的

int exgcd(int a,int b,int&x,int &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    int r = exgcd(b,a%b,x,y);
    int temp = y;
    y = x-(a/b)*y;
    x=temp;
    return r;
}

 应用:NOIP2012 同余方程

[Code+#7]同余方程 - 洛谷

求关于x的同余方程ax ≡ 1 (mod b)的最小正整数解。 就是ax+by=1中x最小的正整数解。

四:DFS

1:DFS

解决问题:八皇后,递归求全排列,递推求全排列

个人感觉比较难,重点是找到边界 

void dfs(...) { //递归参数:当前枚举到哪一步 
	if(到达终点) {
		记录答案
		return;
	}
	if(当前状态不合法)	return;
	if(达到剪枝条件)	return;
	for(...) { //枚举状态 
		if(将要访问的状态不合法)	continue;
		操作
		标记已经访问
		dfs(下一步);
		(还原标记) //回溯法 
	} 
}

 八皇后:        

#include<bits/stdc++.h>
using namespace std;

int ans[10], vis[3][20];

void dfs(int now) {
	if(now == 9) {
		for(int i = 1; i <= 8; i++)	cout << ans[i] << " ";
		cout << "\n";
		return;
	}
	for(int i = 1; i <= 8; i++) {
		if(vis[0][i] || vis[1][now + i] || vis[2][now - i + 8])	continue;
		ans[now] = i;
		vis[0][i] = 1; vis[1][now + i] = 1; vis[2][now - i + 8] = 1;
		dfs(now + 1);
		vis[0][i] = 0; vis[1][now + i] = 0; vis[2][now - i + 8] = 0;
	}
}

int main() {
	dfs(1);
	return 0;
} 

 五:综述

革命尚未成功,同志继续努力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值