例题详解Java dfs与记忆化搜索和分治递归算法的使用
目录一、dfs(深度优先搜索)1.图的dfs2.树的dfs二、记忆化搜索1.普通递归:O(2^n)2.记忆化搜索: O(n)三、分治四、算法题1.dia和威严 示例2.小红点点点 示例13.kotori和素因子 示例1 示例24.kotori和糖果 示例
一、dfs(深度优先搜索)
1.图的dfs
/**
* 深度优先搜索
*
* @param node
* @param set
*/
public void DFS(Node node, Set set) {
if (node == null) {
//当没有节点时,退出此次方法
return;
}
if (!set.contains(node)) {
//没有搜到过就保存,并且继续向下推进
set.add(node);
System.out.print(node.value + " ");
for (Node node1 : node.nexts) {
DFS(node1, set);
}
}
}
2.树的dfs
树(边数=顶点数-1的图)的dfs
public static void dfs(Node treeNode) {http://
if (treeNode == null) {
return;
}
System.out.print(treeNode.value + " ");
// 遍历左节点
dfs(treeNode.left);
// 遍历右节点
dfs(treeNode.right);
}
使用dfs代替状压枚举: dfs 优于 状压枚举
二、记忆化搜索
记忆化搜索,指通过记录已经搜索到的值来降低重复操作次数,从而加快运行速度。
斐波那契数列问题: 1,1,2,3,5,8,... 求斐波那契数列第n项
1.普通递归:O(2^n)
public static int f(int n){
if(n<=1)return 1;
return f(n-1)+f(n-2);
}
2.记忆化搜索: O(n)
static int[] dp = new int[1000] ;
public static int f1(int n){
if(n<=1) return dp[n] = 1;
if(dp[n]!=0)return dp[n];
return dp[n]=f1(n-1)+f1(n-2);
}
三、分治
将问题拆分成子问题进行求解。
例如归并排序: 1,4,7,2,5,8,3,6,9
第一步 拆分: 左边:1,4,7,2 右边:5,8,3,6,9
第二步 递归排序 左边:1,2,4,7 右边:3,5,6,8,9
第三步 合并两个有序数组 左边:1,2,4,7 右边:3,5,6,8,9
四、算法题
1.dia和威严
难度⭐⭐
知识点:dfs
从根开始dfs即可,dfs的过程中就能找到每个点需要的时间,维护一下最大值。
题目描述:
dia是学生会长。她经常有信息要传达给别人。
学生会的阶层等级森严。每个阶级传达信息只能传达到自己的下属。
一个人可以有多个下属,但一个人最多只能有一个上级。(树)
dia作为学生会长,很明显是没有上级的(即全学生会权利最大者)。
已知每个人传达到下属所消耗的时间。(传达给不同的下属,时间不一定相同) 现在dia有一个信息要传达给一个指定者。只有信息接收的指定者才需要理解信息(花费ai的时间)。她不想让效率太慢,于是她想找出最大时间消耗的那个路线(包括信息接收指定者所需要理解信息的时间),这样就能方便整改。
输入描述:
第一行一个正整数n,代表学生会的人数(dia是1号,其他人标记为2号到n号)。 (1≤n≤200000)第二行有n-1个正整数ai,代表从2号到n号,每个人需要理解信息的时间。 (1≤a1≤100)接下来的n-1行,每行有3个正整数x,y,k,代表x是y的上级,x向y传播信息需要消耗k的时间。(1≤x,y≤n,1≤k≤100)
输出描述:
一个正整数,代表dia选定某人作为信息接收指定者后,花费总时间的最大值。
示例
输入
3
3 4
1 2 4
1 3 2
输出
7
说明
若dia指定3号为信息接受者,消耗时间为2+4=6。
若dia指定2号为信息接受者,消耗为4+3=7。
故最大值为7。
备注:
注:只有指定者需要理解信息,传达者不需要花费时间理解信息。
import java.util.*;
import java.io.*;
public class Main{
static class Edge{
int to;
int weight;
//保存子节点,与线权(传播时间)。
Edge(int to,int weight){
this.to = to;
this.weight = weight;
}
}
static ArrayList[] g;
static int maxtime;
static int weight[];
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine()); //n为总人数
weight = new int[n+1];
g = new ArrayList[n+1];
// 每个桶中保存一个ArrayList(可达)
//这里的i代表了第几个数(从1开始)
for(int i = 1;i<=n;i++){
g[i] = new ArrayList();
}
//保存所有点权(理解时间)纪录了从2到n的点权,与数字的位子相对应。
String[] s = br.readLine().split(" ");
for(int i = 0;i weight[i+2] = Integer.parseInt(s[i]);
}
for(int i = 0;i String[] s1 = br.readLine().split(" ");
int x = Integer.parseInt(s1[0]);
int y = Integer.parseInt(s1[1]);
int z = Integer.parseInt(s1[2]);
g[x].add(new Edge(y,z));
}
dfs(1,0);
System.out.println(maxtime);
}
static void dfs(int i ,int time){
if(maxtime
暂时没有评论,来抢沙发吧~