蓝桥杯JAVA练习0224-ALGO-4笔记

ALGO-4 结点选择

结点选择
50%
这道题是树形动态规划,参考了大佬的代码
由于JAVA的一些原因,C++能满分的代码用JAVA只能过一半的数据

首先需要读懂题目
第一行是结点的个数
第二行是每个结点的权
再向下是树的边(不分父子)

建立两个全局二维数组
tree[i][j]=a(a!=0)代表树有一条i到a的边,每行个数取决于i结点和其他结点有几条边
dp[i][0]代表i结点i不选中时的所有权值之和
dp[i][1]代表结点i选中时所有权值之和

首先将结点i的权值存在dp[i][1]中作为初始值
将边存储在tree[][]中,注意由于不区分父子结点,需要双向添加(maketree函数)

重点是dfs方法,深度优先搜索
从结点1开始进行深度优先搜索,需要注意当该结点的父节点子节点相同时,不进行任何操作,以防计算重复

核心的语句

//选择x结点时,添加x相邻的结点x_son未选中时的权值
dp[x][1] += dp[x_son][0];
//不选择x结点时,添加x相邻结点选中或者不选中时最大的值
dp[x][0] += Math.max(dp[x_son][0], dp[x_son][1]);

最终的结果就是输出结点1选中或者未选中中较大的值

为了搞懂这个过程最好画个图模拟过程以便更好地理解
在这里插入图片描述

code
import java.util.Scanner;

public class Main {

	static int tree[][];
	static int dp[][];

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		tree = new int[n + 1][n + 1];
		dp = new int[n + 1][2];
		int i, j;
		for (i = 0; i < n; i++) {
			dp[i + 1][1] = scanner.nextInt();
		}
		for (i = 1; i < n; i++) {
			int x = scanner.nextInt();
			int y = scanner.nextInt();
			maketree(x, y);
		}
		dfs(1, 0);
		System.out.println(Math.max(dp[1][0], dp[1][1]));

	}

	public static void maketree(int x, int y) {
		int i = 0, j = 0;
		while (tree[x][i] != 0)
			i++;
		tree[x][i] = y;
		while (tree[y][j] != 0)
			j++;
		tree[y][j] = x;
	}

	public static void dfs(int x, int x_father) {
		int x_son = tree[x][0];
		int i, j, k;
		for (i = 0; x_son != 0; i++) {
			x_son = tree[x][i];
			if (x_son != x_father) {
				dfs(x_son, x);
				dp[x][1] += dp[x_son][0];
				dp[x][0] += Math.max(dp[x_son][0], dp[x_son][1]);

			}

		}
	}

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值