算法--2023.1.15

1.力扣198--打家劫舍

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n+1];
        dp[0] = 0;
        dp[1] = nums[0];
        //状态转移:
        //遍历到第i个节点,比较遍历到前一个节点与前两个节点加上当前节点的最大值,最为第i个节点的值
        for(int i = 2;i<=n;i++){
            dp[i] = Math.max(nums[i-1]+dp[i-2],dp[i-1]);
        }
        return dp[n];
    }
}

2.力扣213--打家劫舍2

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        if(n == 1){
            return nums[0];
        }
        //原理同上,在此基础上,增加一个dp数组
        int[] dp1 = new int[n+1];
        //第二个dp数组遍历到第一个节点的时候,dp[1]设置为0代表不用低一个节点的值,这样就一定可以用最后一个节点
        int[] dp2 = new int[n+1];
        dp1[0] = 0;dp1[1] = nums[0];
        dp2[0] = 0;dp2[1] = 0;
        for(int i = 2; i<= n;i++){
            dp1[i] = Math.max(dp1[i-2]+nums[i-1],dp1[i-1]);
            dp2[i] = Math.max(dp2[i-2]+nums[i-1],dp2[i-1]);
        }
        //返回的时候,比较dp1倒数第二个节点与dp2的最后一个节点
        //两种情况:
        //1.如果没用到第一个节点的值,则dp2[n]>dp1[n-1];
        //1.如果在dp1中用到了第一个节点的值,dp2可以保证一定没有用到,则比较dp1[n-1]与dp2[n]的值即可
        return Math.max(dp1[n-1],dp2[n]);
    }
}

3.力扣337--打家劫舍3

class Solution {
    //树形dp问题,考虑一个节点的动态规划即可。
    public int rob(TreeNode root) {
        int[] temp =dfs(root);
        return Math.max(temp[0],temp[1]);
    }
    int[] dfs(TreeNode root){
        if(root == null){
            return new int[]{0,0};
        }
        //采用后续遍历的方法进行遍历
        //每次返回值是两个值,用数组保存,第一个值代表不包含当前节点值的最大值,第二个值表示可能会包含当前节点
        int[] x = dfs(root.left);
        int[] y = dfs(root.right);
        //根结点的逻辑
        //1.第一个值就是左右子节点中分别返回的最大值相加
        //2.第二个值不能包含左右子节点,所以是左右叶子节点的第一个值相加
        return new int[]{Math.max(x[0],x[1]) + Math.max(y[0],y[1]), x[0] + y[0] + root.val};
    }
}

 4.acwing285--没有上司的舞会

import java.util.Scanner;

public class acwing285 {

    public static int n;
    public static int[] h,e,ne;
    public static int idx;
    public static int[] happyValue;
    public static boolean[] hasFather;
    public static int[][] f;


//建立树或者图,插入边的固定方法,若只建立单链表,只记录头节点h即可不需要数组
//e[]存子节点的坐标,h[]存父节点第一个节点的坐标,每个节点具体的值用happyValue[]存
    public static void add(int a, int b){
        e[idx] = b; ne[idx] = h[a]; h[a] = idx++;
    }

//树的动态规划
    public static void dfs(int u){
        f[u][1] = happyValue[u];
        for(int i = h[u];i!=0;i = ne[i]){
            int j = e[i];
            dfs(j);
            f[u][1] += f[j][0];
            f[u][0] += Math.max(f[j][0],f[j][1]);
        }
    }
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        happyValue = new int[n+1];
        h = new int[n+1]; e = new int[n+1]; ne = new int[n+1];
        f = new int[n+1][2];
        hasFather = new boolean[n+1];
        for(int i = 1;i<=n;i++){
            happyValue[i] = in.nextInt();
        }
        for(int i = 0;i<n-1;i++){
            int a = in.nextInt(), b = in.nextInt();
            add(b,a);
            hasFather[a] = true;
        }
        int root = 1;
        while(hasFather[root]){
            root++;
        }
        dfs(root);
        System.out.println(Math.max(f[root][0],f[root][1]));

    }
}

  

 

  

 

posted @ 2023-01-15 12:15  lyjps  阅读(22)  评论(0)    收藏  举报