动态规划习题

DP习题

243. 快递运输【买手办问题!!!】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().trim().split(",");
        int[] arr = new int[split.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        int size = in.nextInt();
        int[][] dp = new int[arr.length + 1][size + 1];
        for (int i = 1; i < dp.length; i++) {
            for (int j = size; j >= 0; j--) {
                if (j >= arr[i - 1]){
                    dp[i][j] = Math.max(dp[i - 1][j],  dp[i - 1][j - arr[i - 1]] + 1);
                }else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        System.out.println(dp[arr.length][size]);
  }


}

Melon的难题【01背包问题中“装满背包的最少物品数问题】----> 背包从小到大

注意初始化问题,第一行除了第一个都要赋值最大值【物品个数】!!!

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        int count = in.nextInt();
        int[] arr = new int[count];
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.nextInt();
            sum += arr[i];
        }
        if (sum % 2 != 0){
            System.out.println(-1);
            return;
        }
        int[][] dp = new int[count + 1][sum / 2 + 1];   //  装满背包所需最小物品数量
        Arrays.fill(dp[0], count);
        dp[0][0] = 0;
        for (int i = 1; i < dp.length; i++) {
            for (int j = 0; j <= sum / 2; j++) {
                if (j >= arr[i - 1]){  //  注意等号
                    dp[i][j] = Math.min(dp[i - 1][j], dp[i -1][j - arr[i - 1]] + 1);  //  求个数
                }else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        //// 如果装满背包的最少物品数为n, 则说明没有平分方案,因为n个雨花石的重量之和为sumV,而背包的承重是bag = sumV / 2
        if (dp[dp.length - 1][sum / 2] == count){  // dp[i][j]:容量为 j 的背包最少能用 i 个物品装满`
            System.out.println(-1);
            return;
        }
        System.out.println(dp[dp.length - 1][sum / 2]);
    }
}

打印 DP 数组如下:

代表团坐车

一维滚动数组

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(",");
        int[] arr = new int[split.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        int count = in.nextInt();
        int[] dp = new int[count + 1];
        dp[0] = 1;
        for (int i : arr) {
            for (int j = count; j >= 0; j--) {
                if (j >= i){
                    dp[j] = dp[j] + dp[j - i];
                }
            }
        }
        System.out.println(dp[count]);
    }
}

二维

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(",");
        int[] arr = new int[split.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        int count = in.nextInt();
        int[][] dp = new int[arr.length + 1][count + 1];
        dp[0][0] = 1;
       for (int i = 1; i <= dp.length - 1 ; i++) {
            for (int j = count; j >= 0; j--) {
                if (j >= arr[i - 1]){
                    dp[i][j] = dp[i - 1][j] + dp[i - 1][j - arr[i -1]];
                }else {
                    dp[i][j] = dp[i - 1][j];
                }
            }
        }
        System.out.println(dp[dp.length - 1][count]);
    }
}

192. 跳格子【打家劫舍】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        int[] arr = new int[split.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        int[] dp = new int[arr.length + 2];
        for (int i = 2; i < dp.length; i++) {
            //  不要这个
            //  要这个:那么i - 1 就不要了,dp[i- 2] + 当前
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + arr[i - 2]);
        }
        System.out.println(dp[dp.length - 1]);
    }
}

193. 跳格子2【打家劫舍2】

这道题中的房屋是首尾相连的,第一间房屋和最后一间房屋相邻,因此第一间房屋和最后一间房屋不能在同一晚上偷窃

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(" ");
        int[] arr = new int[split.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        int[] arr1 = Arrays.copyOfRange(arr, 0, arr.length - 1);
        int[] arr2 = Arrays.copyOfRange(arr, 1, arr.length);
        System.out.println(Math.max(getMax(arr1), getMax(arr2)));
    }
    public static int getMax(int[] arr){
        int[] dp = new int[arr.length + 2];
        for (int i = 2; i < dp.length; i++) {
            dp[i] = Math.max(dp[i -1], dp[i -2] + arr[i - 2]);
        }
        return dp[dp.length - 1];
    }
}

LeetCode 337 打家劫舍Ⅲ【树型DP】

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
	public int rob(TreeNode root) {
		//	1. 不要当前
		//	2. 要当前的
		int[] result = getResult(root);
		return Math.max(result[0], result[1]);
	}
	public int[] getResult(TreeNode root){
		if (root == null){
			return new int[]{0, 0};
		}
		int[] left = getResult(root.left);
		int[] right = getResult(root.right);
		int val1 = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);	//	不要当前的,它的子节点不一定要 ===> 取最大值即可
		int val2 = root.val + left[0] + right[0];	//	偷 cur ===> 那么左右就不能要了
		return new int[]{val1, val2};
	}
}

通过软盘拷贝文件

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int N;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        N = Integer.parseInt(in.nextLine());
        int[] arr = new int[N];
        for (int i = 0; i < N; i++) {
            arr[i] = Integer.parseInt(in.nextLine());
        }
        int target = 1474560 / 512;
        int[][] dp = new int[N + 1][target + 1];
        for (int i = 1; i <= N; i++) {
            for (int j = target; j >= 0; j--) {
               int weight = (int) Math.ceil(arr[i - 1] / 512.0);
               int value = arr[i - 1];
               if (j >= weight){
                   dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight] + value);
               }else {
                   dp[i][j] = dp[i - 1][j];
               }
            }
        }
        System.out.println(dp[N][target]);
    }
}

字符串加密

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
          StringBuilder sb = new StringBuilder();
        long[] arr = new long[50];
        arr[0] = 1;
        arr[1] = 2;
        arr[2] = 4;
        for (int i = 3; i < arr.length; i++) {
            arr[i] = arr[i - 1] + arr[i - 2] + arr[i - 3];
        }

        Scanner in = new Scanner(System.in);
        int count = Integer.parseInt(in.nextLine());    //  多少行输入数据
        for (int i = 0; i < count; i++) {
            String temp = "";
            String str = in.nextLine(); //  只含有小写字母(长度 <= 50)
            for (int j = 0; j < str.length(); j++) {
                char c = str.charAt(j);
                if (c - 'a' + arr[j] <= 25){
                    c =  (char) (c +  arr[j]);
                }else {
                    c = (char) ('a' + ((c - 'a' + arr[j]) % 26));
                }
                temp = c + "";
                sb.append(temp);
            }
            sb.append("\r\n");
        }

        System.out.println(sb.toString().trim());
    }
}

数列描述

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
      Scanner in = new Scanner(System.in);
        int count = in.nextInt();
        String[] dp = new String[count + 1];
        dp[0] = "1";
        for (int i = 1; i < dp.length; i++) {
            String s = dp[i - 1] + "";
            StringBuilder sb = new StringBuilder();
            StringBuilder res = new StringBuilder();
            for (int j = 0; j < s.length(); j++) {
                sb.append(s.charAt(j));
                if (j + 1 < s.length() && s.charAt(j) == s.charAt(j + 1)){  //  下一个和现在相同就一直 continue
                    continue;
                }
                res.append(sb.length() + sb.substring(0, 1));
                sb.delete(0, sb.length());  //  清空 sb
            }
            dp[i] = res.toString();
        }
        System.out.println(dp[dp.length - 1]);
    }
}

猴子爬山

import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int count = Integer.parseInt(in.nextLine());
        long[] dp = new long[count + 1];
        dp[0] = 1;
        dp[1] = 1;
        dp[2] = 1;
        for (int i = 3; i < dp.length; i++) {
            dp[i] = dp[i - 1] + dp[i - 3];
        }
        System.out.println(dp[count]);
    }
}

翻牌求最大分【玩牌高手】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
         Scanner in = new Scanner(System.in);
        String[] split = in.nextLine().split(",");
        int[] arr = new int[split.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }
        int[] dp = new int[arr.length + 3];
        for (int i = 3; i < dp.length; i++) {
            dp[i] = Math.max(dp[i - 3], dp[i - 1] + arr[i - 3]);
        }
        System.out.println(dp[dp.length - 1]);
    }
}

数组连续和【前缀和】

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        int count = in.nextInt();
        int target = in.nextInt();
        int[] arr = new int[count];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = in.nextInt();
        }
        long res = 0;
        int[] sum = new int[arr.length + 1];
        for (int i = 1; i < sum.length; i++) {
            sum[i] = sum[i - 1] + arr[i - 1];
            if (sum[i] < target){   //  1. 当前【最长的】不可
                continue;
            }
            res += 1;   //  2. 当前可
            int cur = i - 1;
            //  所有数都是整数,那么 sum[] 数组是递增的
            //  看前缀和,如果不符合就一直向前推进,如果符合了:说明有 cur 个符合规定
            while (cur >= 1 && sum[i] - sum[cur] < target){
                cur--;
            }
            res += cur;
        }
        System.out.println(res);
    }
}

最大矩阵和

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int row;
    static int col;
    static int[][] arr;

    public static void main(String[] args) {
       Scanner in = new Scanner(System.in);
        row = in.nextInt();
        col = in.nextInt();
        arr = new int[row][col];
        int res = Integer.MIN_VALUE;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                arr[i][j] = in.nextInt();
            }
        }
        for (int i = 0; i < row; i++) {
            //  单行
            res = Math.max(res, getMax(arr[i]));
            for (int j = i + 2; j <= row; j++) { //  多行
                int[][] temp = Arrays.copyOfRange(arr, i, j);
                int[] col = getCol(temp);
                int max = getMax(col);
                res = Math.max(res, max);
            }
        }
        System.out.println(res);
    }
     public static int getMax(int[] arr){
        int[] dp = new int[arr.length + 1];
        int max = Integer.MIN_VALUE;
        for (int i = 1; i < dp.length; i++) {
            //  有用才要
            dp[i] = Math.max(dp[i - 1], 0) + arr[i - 1];
            max = Math.max(max, dp[i]);
        }
        return max;
    }

    public static int[] getCol(int[][] arr){
        int row = arr.length;
        int col = arr[0].length;
        int[] temp = new int[col];
        for (int i = 0; i < col; i++) {
            for (int j = 0; j < row; j++) {
                temp[i] += arr[j][i];
            }
        }
        return temp;
    }
}

字符串划分【先求 sum:sum1, sum2】===> 返回被砍掉的 2 个

import java.util.Scanner;
import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    static int[] arr;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String s = in.nextLine();
        arr = new int[s.length()];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = s.charAt(i);
        }
        int sum = 0;
        for (int i : arr) {
            sum += i;
        }
        int l = 0;
        int r = arr.length - 1;
        int sum1 = arr[0];
        int sum2 = arr[arr.length - 1];
        while (l < r){
            if (sum1 == sum2){
                if (sum - sum1 - sum2 - arr[l + 1] - arr[r - 1] == sum1){
                    System.out.println((l + 1) + "," + (r - 1));  //  返回被砍掉的 2 个
                    return;
                }else {
                    l++;
                    r--;
                    sum1 += arr[l];
                    sum2 += arr[r];
                }
            }else {
                if (sum1 < sum2){
                    l++;
                    sum1 += arr[l];
                }else {
                    r--;
                    sum2 += arr[r];
                }
            }
        }
        System.out.println("0,0");
    }
}

数字游戏【前缀和】

import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
         Scanner in = new Scanner(System.in);
        while (in.hasNextLine()){
            String s = in.nextLine();
            if ("".equals(s)){
                break;
            }
            String[] split = s.split(" ");
            int len = Integer.parseInt(split[0]);
            int target = Integer.parseInt(split[1]);
            int[] arr = new int[len];
            String[] temp = in.nextLine().split(" ");
            for (int i = 0; i < arr.length; i++) {
                arr[i] = Integer.parseInt(temp[i]);
            }
            System.out.println(Judge(arr, target));
        }
    }
   public static int Judge(int[] arr, int target){
        int[] sum = new int[arr.length + 1];
        List<Integer> list = new ArrayList<>();
        for (int i = 1; i < sum.length; i++) {
            sum[i] = sum[i - 1] + arr[i - 1];
            if (sum[i] % target == 0){
                return 1;
            }
            if (list.size() != 0){
                for (Integer integer : list) {
                    if ((sum[i] - integer) % target == 0){
                        return 1;
                    }
                }
            }
            list.add(sum[i]);
        }
        return 0;
    }
}

查询接口成功率最优时间段【由于求最长的,所以左侧一直是从 0 开始推进就好了!!! 找到就 break】

import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int minAverageLost = Integer.parseInt(in.nextLine());
        String[] split = in.nextLine().split(" ");
        int[] arr = new int[split.length];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = Integer.parseInt(split[i]);
        }

        List<Time> list = new ArrayList<>();
        int[] sum = new int[arr.length + 1];
        for (int i = 1; i < sum.length; i++) {
            sum[i] = sum[i - 1] + arr[i - 1];
            int index = 0;
            while (index < i){
                int temp = (int) Math.ceil((sum[i] - sum[index]) / (double)(i - index));
                if (temp <= minAverageLost){
                    list.add(new Time(index, i - 1));   //  坐标从 1 开始, 减去 1
                    break;
                }
                index++;
            }
        }

        Collections.sort(list, new Comparator<Time>() {
            @Override
            public int compare(Time o1, Time o2) {
                int len1 = o1.right - o1.left;
                int len2 = o2.right - o2.left;
                if (len1 != len2){
                    return len2 - len1;  //  1. 长度大的在前
                }
                return o1.left - o2.left;  //  长度相同时,left 优先
            }
        });
        if (list.size() == 0){
            System.out.println("NULL");
            return;
        }
        int len = list.get(0).right - list.get(0).left;
        StringBuilder res = new StringBuilder();
        for (Time time : list) {
            if (time.right - time.left == len){
                res.append(time.left + "-" + time.right + " ");
            }
        }
        System.out.println(res.toString().trim());
    }
}

class Time{
    int left;
    int right;

    public Time(int left, int right) {
        this.left = left;
        this.right = right;
    }
}

高效的任务规划【按照运行时间降序排序】

import java.util.Scanner;
import java.util.*;


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int total = Integer.parseInt(in.nextLine());
        for (int i = 0; i < total; i++) {
            int count = Integer.parseInt(in.nextLine());
            List<Machine> list = new ArrayList<>();
            for (int j = 0; j < count; j++) {
                String s = in.nextLine();
                String[] split = s.split(" ");
                int time1 = Integer.parseInt(split[0]);
                int time2 = Integer.parseInt(split[1]);
                list.add(new Machine(time1, time2));
            }
            int config_time = 0;
            int res = 0;
            Collections.sort(list, (o1, o2) -> {
                return o2.time2 - o1.time2; //  运行时间长的先来
            });
            for (Machine machine : list) {
                config_time += machine.time1;
                int time = config_time + machine.time2;
                res = Math.max(res, time);
            }
            System.out.println(res);
        }
    }
}

class Machine{
    int time1;
    int time2;

    public Machine(int time1, int time2) {
        this.time1 = time1;
        this.time2 = time2;
    }
}
posted @ 2023-10-12 12:30  爱新觉罗LQ  阅读(41)  评论(0编辑  收藏  举报