Algorithm Practice Record【1】

前言

刷一题更一题

工具类

下文可能出现PrintArrsTwoUtils.printArr();方法。此为打印二维数组方法,可以删除或注释掉。也可以导入执行,不影响结果,只会打印控制台,可用于打断点分析执行。

import java.util.Arrays;

/**
 * 打印二维数组方法
 */
public class PrintArrsTwoUtils {
    static void printArr(int[][] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.println(Arrays.toString(arr[i]));
        }
        System.out.println("————————————————————————");
    }
    static void printArr(boolean[][] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.println(Arrays.toString(arr[i]));
        }
        System.out.println("————————————————————————");
    }
    static void printArr(String[][] arr){
        for (int i = 0; i < arr.length; i++) {
            System.out.println(Arrays.toString(arr[i]));
        }
        System.out.println("————————————————————————");
    }
}

「动态规划一青蛙跳台阶」

问题描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

代码案例解析

import java.util.Scanner;

public class 动态规划一青蛙跳台阶 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int num = in.nextInt();
        int[] dp = new int[num+1];
        dp[0]=0;
        dp[1]=1;
        dp[2]=2;
        for (int i = 3; i <= num; i++) {
            dp[i] = dp[i-1]+dp[i-2];
        }
        System.out.println(dp[num]);
    }
}

「动态规划一机器人走网格不同路径」

题目描述
一个机器人位于一个 m x n 网格的左上角 。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角有多少种走法?
结果案例
案例1:32的方格 共3条路径;
案例2:7
3的方格 共28条路径。

代码案例解析

public class 动态规划一机器人网格不同路径 {
    public static void main(String[] args) {
        int row = 3;
        int clo = 7;
        int[][] dp = new int[row][clo];
        for (int i = 0; i < row; i++) {
            dp[i][0] = 1;
        }
        for (int i = 0; i < clo; i++) {
            dp[0][i] = 1;
        }
        for (int i = 1; i < row; i++) {
            for (int j = 1; j < clo; j++) {
                dp[i][j] = dp[i][j-1] + dp[i-1][j];
            }
        }
        System.out.println(dp[row-1][clo-1]);
    }
}

「动态规划一二维矩阵最小和路径」

问题描述
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
举例
输入:
arr = [
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 7
解释
因为路径 1→3→1→1→1 的总和最小。

代码案例解析

import java.util.Scanner;

public class 动态规划一二维矩阵最小和路径 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int row = in.nextInt();
        int clo = in.nextInt();
        int[][] arr = new int[row][clo];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < clo; j++) {
                arr[i][j] = in.nextInt();
            }
        }
        // 最右侧列只能往下,则可以确定固定累加值
        for (int i = row-2; i >=0; i--) {
            arr[i][clo-1] = arr[i][clo-1]+arr[i+1][clo-1];
        }
        // 最下侧行只能往右,则可以确定固定累加值
        for (int i = clo-2; i >=0; i--) {
            arr[row-1][i] = arr[row-1][i]+arr[row-1][i+1];
        }
        // 由右下往左上推算最小路径和  i,j为索引
        for (int i = row-2; i >=0; i--) {
            for (int j = clo-2; j >=0; j--) {
                arr[i][j] = arr[i][j]+Math.min(arr[i+1][j],arr[i][j+1]);
            }
        }
        System.out.println(arr[0][0]);
    }
}

「动态规划一01背包」

题目描述
N件物品和容量为V的背包,每个物品只能使用一次。
第i物品有体积Vi和价值Wi
输入描述
求解哪些物品装入背包,总体积不超过背包,且总价值最大。
输入第一行N V,表示N个物品和背包体积V
加下来有N行,每行两个整数vi,wi分别表示第i件的体积和价值。
输入样例
4 5
1 2
2 4
3 4
4 5
输入样例
8

代码案例解析

import java.util.Scanner;

public class 动态规划一01背包 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int size = in.nextInt(); // 物品数量
        int bulk = in.nextInt(); // 背包总体积
        int[][] goods = new int[size+1][2];
        // 初始化物品信息二维数组
        for (int i = 1; i <= size; i++) {
            goods[i][0] = in.nextInt();// 体积
            goods[i][1] = in.nextInt();// 价值
        }
        int[][] dp = new int[size+1][bulk+1]; // 用size个物品,装bulk体积的包,的最大价值dp[][]
        // 当size为0时,不论体积多大背包的价值为0
        for (int i = 0; i <= bulk; i++) {
            dp[0][i] = 0;
        }
        // 当背包容积为0时,放不下体积>0的所有物品,所以价值一定为0
        for (int i = 0; i <= size; i++) {
            dp[i][0] = 0;
        }
        for (int i = 1; i <= size; i++) {
            for (int j = 1; j <= bulk; j++) {
                if (goods[i][0]>j){ // 如果物品体积大于背包,则不放入
                    dp[i][j] = dp[i-1][j];
                }else { // 如果体积小于等于,则可选择放或不放,放的话(放入之后,比对的是,还用当前0~i种物品装j重量的最大可能:之前一定计算过。并非只用第i种来填满剩余j)dp[i-1][j]
                    int i1 = dp[i - 1][j];
                    int i2 = dp[i - 1][j - goods[i - 1][0]];
                    int i3 = goods[i - 1][1];
                    dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-goods[i][0]]+goods[i][1]);
                }
            }
        }
        System.out.println(dp[size][bulk]);
    }
}

「动态规划一完全背包」

题目描述
有N种物品和一个容量为V的背包,每种物品都有无限件可用(这也是与01背包的区别)。
第i种物品的体积是Vi,价值是Wi。求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。
题目描述
输入第一行N和V,表示N种物品和背包体积V
加下来有N行,每行两个整数vi,wi分别表示第i种的体积和价值。
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例
10

代码案例解析

import java.util.Scanner;

public class 动态规划一完全背包 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int size = in.nextInt(); // 物品数量
        int bulk = in.nextInt(); // 背包总体积
        int[][] goods = new int[size+1][2];
        // 初始化物品信息二维数组
        for (int i = 1; i <= size; i++) {
            goods[i][0] = in.nextInt();// 体积
            goods[i][1] = in.nextInt();// 价值
        }
        int[][] dp = new int[size+1][bulk+1]; // 用size个物品,装bulk体积的包,的最大价值dp[][]
        // 当size为0时,不论体积多大背包的价值为0
        for (int i = 0; i <= bulk; i++) {
            dp[0][i] = 0;
        }
        // 当背包容积为0时,放不下体积>0的所有物品,所以价值一定为0
        for (int i = 0; i <= size; i++) {
            dp[i][0] = 0;
        }
        for (int i = 1; i <= size; i++) {
            for (int j = 1; j <= bulk; j++) {
                if (goods[i][0]>j){ // 如果物品体积大于背包,则不放入
                    dp[i][j] = dp[i-1][j];
                }else { // 如果体积小于等于,则可选择放或不放,放的话
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-goods[i][0]]+goods[i][1]);
                }
            }
        }
        System.out.println(dp[size][bulk]);
    }
}

「动态规划一多重背包」

题目描述
有N种物品和一个容量为V的背包,每种物品都有都有S个。
第i种物品的体积是Vi,价值是Wi,最多有Si个。
输入描述
求解将哪些物品装入背包可使这些物品的体积总和不超过背包容量,且价值总和最大。
输入第一行N V,表示N种物品和背包体积V
加下来有N行,每行两个整数vi,wi分别表示第i种的体积和价值。
输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例
10

代码案例解析

import java.util.Scanner;

public class 动态规划一多重背包 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int size = in.nextInt(); // 物品数量
        int bulk = in.nextInt(); // 背包总体积
        int[][] goods = new int[size+1][3];
        // 初始化物品信息二维数组
        int count = 0;// 商品总数,用于初始化所有商品
        for (int i = 1; i <= size; i++) {
            goods[i][0] = in.nextInt();// 体积
            goods[i][1] = in.nextInt();// 价值
            goods[i][2] = in.nextInt();// 数量
            count += goods[i][2];
        }
        // 平铺可用于装包的物品
        int[][] allGoods = new int[count+1][2];
        int allIndex = 1;
        for (int i = 1; i <= size; i++) {
            for (int j = 0; j < goods[i][2]; j++) {
                allGoods[allIndex][0] = goods[i][0];
                allGoods[allIndex][1] = goods[i][1];
                allIndex++;
            }
        }
        int[][] dp = new int[count+1][bulk+1]; // 用平铺后的count种物品,装bulk体积的包,的最大价值dp[][]
        // 当size为0时,不论体积多大背包的价值为0
        for (int i = 0; i <= bulk; i++) {
            dp[0][i] = 0;
        }
        // 当背包容积为0时,放不下体积>0的所有物品,所以价值一定为0
        for (int i = 0; i <= count; i++) {
            dp[i][0] = 0;
        }
        for (int i = 1; i <= count; i++) {
            for (int j = 1; j <= bulk; j++) {
                if (allGoods[i][0]>j){ // 如果物品体积大于背包,则不放入
                    dp[i][j] = dp[i-1][j];
                }else { // 如果体积小于等于,则可选择放或不放,放的话
                    dp[i][j] = Math.max(dp[i-1][j],dp[i][j-allGoods[i][0]]+allGoods[i][1]);
                }
            }
        }
        System.out.println(dp[count][bulk]);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值