本文主要是介绍搜索(未完结版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前言
图的基础与遍历
图的存储方式
邻接表
List<int []>list[N];
list[x]存储x的所有出点的信息。
list[i][j]={first,second}其中first表示从i出发的某个出点的编号,second表示边权。
list[1]={{2,0},{3,0}} 1这个点有2和3连个出边
邻接矩阵
d[i][j]表示从i到j的边的距离(一般情况下为最短距离)
d[1,2]=0(表示从1到2有一条边)
d[4,3]=-1(不存在对应的边)
DFS(深度优先搜索)
一条道走到黑,走过的路不再走(一种情况尝试到底)
递归
搜索的要点:
1:选定初始状态
2:遍历当前初始状态或状态所产生的合法状态,产生的新状态进入递归
3:检查目标状态是否是合法状态,是则返回,否则继续遍历,重复2-3步骤
常用模板
public static void dfs(){if(当前状态==目标状态){return;}for(寻找新状态){if(状态合法){dfs(新状态);}}
}
顺序不确定,只要走完就行
回溯
从一条路往前走,能进则进,不能进则退
全排列
回溯的模板与dfs的常用模板相同
public static void dfs(){if(当前状态==目标状态){return;}for(寻找新状态){if(状态合法){
//标记当前状态已访问dfs(新状态);
//撤销标记}}
}
图论中的模板
boolean<N> v;//v[i]=true说明i点已经走过 标记数组
void dfs(int x){v[x]=true;//进来对x,打上标记for(int y:list[x]){if(v[y]) continue;//已经打过标记的话,跳过else dfs(y);//否则进入y这个结点}}
BFS(宽度优先搜索)
一层一层往外走,每个点只走一次
通常用于求边权相等情况下的最短距离
BFS一般用队列来实现
boolean <N> vis;//标记数组,v[i]=true表示点已经走过了
queue<int> q;//q表示带拓展的队列
while(q.size>0){//只要队列不为空就一直走int x=q.pop();//弹出来if(v[x]) continue;v[x]=true;//没有走过这个标记for(int y:list[x]){q.push(y);}//遍历这个点的所有出点,压入队列中}
编号3891帮派弟位
问题描述
小明在游戏中参加了一个帮派,这一天他突然想知道自己在帮派中是什么地位,但是帮派的查询系统突然坏了,目前只能知道每个人的附属关系,请问你能帮帮他重建关系网并找出他的地位吗?
给定一个正整数 n ,代表该帮派的总人数,并且小明的序号是 m ,给出这 n 个人中每个人的附属关系,确保给出的关系网为一棵树。帮派地位的定义是按照自己手下有多少帮众决定的,注意手下的手下也算是自己的手下。如果手下的帮众相同则按序号较小的在前面。你能帮助小明找到自己的帮派地位吗?
输入格式
第一行,两个正整数 n (1≤n≤105) 和 m (1≤m≤n) ,代表该帮派的总人数以及小明的序号。
接下来 n−1 行,每行两个正整数,格式如下:
l r
(1≤l,r≤n) , 代表序号为 l 的人附属于序号为 r 的人。- 输出格式
一行,包含 11 个正整数,输出按手下人数多少排序后小明的排名。 - 样例输入
6 4 2 1 3 1 4 2 5 2 6 5
样例输出
5
代码
import java.util.*;
// 1:无需package
// 2: 类名必须Main, 不可修改public class Main {static List<Integer> []list;public static void main(String[] args) {// TODO Auto-generated method stubScanner scan=new Scanner(System.in);int n=scan.nextInt();int m=scan.nextInt();list = new List[n+1];for(int i=0;i<n+1;i++) {list[i]=new ArrayList<>();}//存储点int []a=new int [n+1];//存储入度for(int i=0;i<n-1;i++) {int l=scan.nextInt();int r=scan.nextInt();list[r].add(l); a[l]++;}int root=0;for(int i=1;i<=n;i++) {//总人数是1-nif(a[i]==0) {root=i;break;}}//找到根节点了int []dp=new int[n+1];//每个结点值的大小dfs(root,dp);int ans=1;for(int i=1;i<m;i++) {if(dp[i]>=dp[m]) {ans++;}//前半部分}for(int i=m+1;i<n;i++) {if(dp[i]>dp[m]) {ans++;}}System.out.println(ans);}public static void dfs(int root,int[] dp) {for(int y:list[root]) {dfs(y,dp);dp[root]+=dp[y]+1;//子节点的子节点数量以及他自己}}}
全排列问题(回溯)
问题描述
输入一个数组n,输出1到n的全排列。
代码
package lanqiaoyun;
import java.util.*;public class quanpai {static List<List<Integer>> list=new ArrayList<>();//存放全排列public static void main(String[] args) {// TODO Auto-generated method stubScanner scan=new Scanner(System.in);int n=scan.nextInt();int []v=new int [n+1];//表示当前数组访问List<Integer> res=new ArrayList<>();//当前集合存储了多少个元素dfs(n,v,res);for(List<Integer> x:list) {for(int y:x) {System.out.print(y+" ");}System.out.println("");}}public static void dfs(int n,int[] v,List<Integer> res) {if(res.size()==n) {//表示当前集合中已经有n个元素,完成了全排列list.add(new ArrayList<>(res));return ;}for(int i=1;i<=n;i++) {if(v[i]==1) {continue;}//不合法,当前数已经被访问过了res.add(i);v[i]=1;dfs(n,v,res);res.remove(res.size()-1);v[i]=0;}}}
这篇关于搜索(未完结版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!