• 清北学堂—2020.1提高储备营—Day 1 morning(模拟、枚举、搜索)


    qbxt Day 1 morning

    ——2020.1.17 济南 主讲:李佳实

    目录一览

    1.模拟和枚举
    2.基础搜索算法(DFS、BFS、记忆化搜索)以及进阶搜索算法(纯靠自学)

    总知识点:基础算法

    一、模拟和枚举

    1.算法描述:模拟,顾名思义就是按照题目的要求,它让你做什么,按照要求做。
    2.例题一览:
    (1)【算法:枚举】寻找三位数
    题目描述:
    将1, 2, …, 9共9个数分成三组,分别组成三个三位数,且使这 三个三位数构成1: 2: 3的比例,试求出所有满足条件的三位数。

    分析:
    首先我们会轻易的想到可以直接暴力枚举这三位,不过这种做法显然会超时。我们不妨转变一下思路,直接枚举这个三位数,可是如果从100到999的话,也显然会超时,而题中还有一个条件“三个”三位数,那我们就可以把1000平均分开,枚举一部分,降低时间复杂度。1000/3约等于333,循环就从100-333循环,而我们根据这一倍的量,计算出2倍、3倍,再判断有没有重复的数字。这道题就完美的解决了。

    代码:(C++版)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define N 1000
    #define M 1000
    using namespace std;
    int time[10];
    void get(int x){
    	time[x%10]++;
    	time[x/10%10]++;
    	time[x/100]++;
    }
    int main(){
    	for(int i=100;i<=333;i++){
    		int x=i,y=i*2,z=i*3;
    		memset(time,0,sizeof(time));
    		get(x);
    		get(y);
    		get(z);
    		bool flag=true;
    		for(int j=1;j<=9;j++) if(time[j]!=1) flag=false;
    		if(flag){
    			cout<<x<<' '<<y<<' '<<z<<endl;
    		}
    	}
    	return 0;
    }
    

    (2)【算法:模拟】河伯阵型
    题目描述:

    分析:没什么好说的,按照题要求的做就是了。

    代码:

    二、搜索

    1.深度优先搜索(DFS)
    (1)算法描述:对于任意的一个图,有一点x,我们寻找与它连通的所有深度更深的点y(若没有,回到上一个点)。若y被访问过,回到x。反之,访问y。如此循环往复。
    (2)特征:若x被访问过,则x的父节点也一定被访问过。每条边至多被访问2次,每个点至多被访问一次。
    (3)代码框架:

    inline void dfs(int x){
    	int i;
    	vis[x]=1;
    	for(i=1;i<=n;i++){
    		if(mp[x][i]&&!vis[i]){
    			dfs(i);
    		}
    	}
    }
    

    (4)使用DFS枚举已知集合的所有子集状态
    分析:对于一个元素a[i],我们有两种选择:选or不选。于是我们DFS求出来的树同时是一棵二叉树。先沿着选的方向到底,在一步步回溯,直到遍历结束。
    代码:

    inline void dfs(int x){
    	if(x>n){
    		//得到了一个子集 
    		return ;
    	}
    	s[++tot]=a[x];
    	dfs(x+1);
    	tot--;
    	dfs(x+1);
    }
    

    (5)DFS枚举1~n的全排列
    分析:见代码
    代码:

    inline void dfs(int x){
    	if(x>n){
    		//得到了一个排列
    		return ; 
    	}
    	int i;
    	for(i=1;i<=n;i++){
    		if(!used[i]){	//没有使用过 
    			p[x]=i;	
    			used[i]=1;	//标记使用 
    			dfs(x+1);
    			used[i]=0;	//清空,准备下一步 
    		}
    	}
    }
    

    (6)DFS判断图中有无环
    分析:判断环我们只要判断图中有无返祖边(后向边)即可。返祖边:两点u,v,且u->v。vis[v] = 1,说明v已经被访问,但其子孙后代还没有被访问完。而u又指向说明u就是v的子孙后代,u->v是一条后向边(返祖边)。

    2.广度优先搜索(BFS)
    (1)工具:队列
    (2)思想:弹出队列的队头,把图中元素加到队尾。
    (3)代码:

    void bfs(){
    	q[tl++]=s;	
    	while(hd!=tl){
    		x=q[hd++];	//弹队头 
    		for(i=1;i<=n;i++){
    			if(mp[x][i]&&!vis[i]){	//连通且没被访问 
    				q[tl++]=i;	//加队尾 
    				vis[i]=1;	//标记访问 
    			}
    		}
    	}
    }
    

    3.记忆化搜索(DFS优化)
    (1)算法分析:省去了重复的部分,使其变的更优。
    (2)代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define N 1000
    #define M 1000
    using namespace std;
    int n,m;
    int u,v,c;
    int s,to[M],l[M],ne[M],pre[N];
    void add(int u,int v,int c)		//加边函数,邻接表存储 
    {
    	to[++s]=v;
    	l[s]=c;
    	ne[s]=pre[u];
    	pre[u]=s;
    }
    int f[N];
    bool vi[N];
    int cal(int k)
    {
    	if(vi[k]) return f[k];
    	vi[k]=true;
    	for(int i=pre[k];i;i=ne[i])
    	{
    		int x=to[i];
    		f[k]=max(f[k],cal(x)+l[i]);
    	}
    	return f[k];
    }
    int main()
    {
    	cin>>n>>m;
    	while(m--)
    	{
    		cin>>u>>v>>c;
    		add(u,v,c);
    	}
    	for(int i=1;i<=n;i++) cout<<i<<' '<<cal(i)<<endl;
    	return 0;
    }
    

    ---------------------------------------------THE END-----------------------------------------------------

    本文欢迎转载,转载时请注明本文链接
  • 相关阅读:
    PPT文档页数显示的增加和更新
    Android http超时选项的测试
    64位win7硬盘安装64位ubuntu 13.04
    为博客园添加目录的配置总结
    Android webview通过http get下载文件下载两次的问题及解决方法
    ubuntu12.04安装搜狗输入法和配置
    samsung Galaxy s2(GT i9100g )刷机升级至4.4小记
    uva 11584 Partitioning by Palindromes
    uva 10534 Wavio Sequence
    poj 1185 炮兵阵地
  • 原文地址:https://www.cnblogs.com/-pwl/p/12208271.html
Copyright © 2020-2023  润新知