提交 79b1c61b 编写于 作者: qq_36480062's avatar qq_36480062

commit

上级 6018f422
package com.shiyu;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
public class tsdt {
public static void main(String[] args) {
int[][] arr = {{3}, {2, 4}, {6, 7, 9}, {4, 2, 6}};
for (int[] ints : arr) {
// System.out.println(Arrays.toString(ints));
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i].length);
Scanner sc = new Scanner(System.in);
ArrayList<Integer> jishu = new ArrayList<>();
ArrayList<Integer> oshu = new ArrayList<>();
Iterator<Integer> iterator = jishu.iterator();
while (iterator.hasNext()) {
Integer next = iterator.next();
System.out.println(next);
}
int[][] dp = new int[arr.length][arr[arr.length - 1].length];
for (int i = 0; i < arr[arr.length - 1].length; i++) {
dp[dp[dp.length - 1][i]][i] = arr[arr.length - 1][i];
}
for (int i = dp.length - 2; i >= 0; i--) {
for (int j = 0; j < dp[i].length-1; j++) {
dp[i][j] = arr[i][j] + Math.min(dp[i + 1][j + 1], dp[i + 1][j]);
while (sc.hasNext()) {
int a = sc.nextInt();
if (a == 1111)
break;
if (a % 2 == 0) {
oshu.add(a);
} else {
jishu.add(a);
}
}
System.out.println(dp[0][0]);
System.out.println(jishu);
System.out.println(oshu);
}
}
package dp;
import java.util.Arrays;
public class 数学三角形 {
public static void main(String[] args) {
int[][] data = {
......@@ -27,13 +29,36 @@ public class 数学三角形 {
System.out.println(dp[0][0]);
}
public static void Max() {
int[][] arr = {
{3},
{2, 4},
{6, 7, 9},
{4, 2, 6}};
int[][] dp = new int[arr.length][arr[arr.length - 1].length + 1];
for (int i = 0; i < arr[arr.length - 1].length; i++) {
dp[arr.length - 1][i] = arr[arr.length - 1][i];
}
System.out.println(Arrays.toString(dp[3]));
for (int i = arr.length - 2; i >= 0; i--) {
for (int j = 0; j <= arr[i].length - 1; j++) {
dp[i][j] = arr[i][j] + Math.max(dp[i + 1][j + 1], dp[i + 1][j]);
}
}
for (int[] ints : dp) {
System.out.println(Arrays.toString(ints));
}
System.out.println(dp[0][0]);
}
/**
* 使用一维数组的解法
*
* @param tri
* @param i
* @param j
*/
public static void MaxSumByOne(int[][] tri,int i,int j){
public static void MaxSumByOne(int[][] tri, int i, int j) {
}
}
package dp;
/**
* 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
* 示例:
* 输入: [-2,1,-3,4,-1,2,1,-5,4],
* 输出: 6
* 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
* 进阶:
* 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
* <p>
* 思路:问题的子数组看做一段区间,由起点或者终点确定一个子数组,两个点中,
* 我们先确定一个点,再去找另一个点,比方说,如果我们确定一个子数组的截止元素在i这个位置,
* 所以dp数组语义就是以i结尾的所有子数组中和最大的是多少,
* 只有两种情况
* 1.{i这个位置的元素,自己成了一个子数组}
* 2.{i这个位置的元素,加上,以i-1结尾的所有子数组中的最大和}
* 当把第i个问题,拆成第i-1个问题,之间的联系变得清晰,最优子结构就体现出来
* dp[i]就是以i结尾的所有子数组中的最大值
* dp方程=dp[i]=max(dp[i-1]+array[i],array[i])
* //化简一下就成了:dp[i] = Math.max(dp[i - 1], 0) + array[i]
* 我觉得化简,语义就不明显了.
* 注意:子数组不能为空,所以要初始化dp[0]=array[0]
*/
public class 最大和连续子数组 {
public static void main(String[] args) {
int[] are = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
System.out.println(dpp(are));
}
public static int[] dp;
public static int dpp(int[] arr) {
int ans = 0;//结果
dp = new int[arr.length];
dp[0] = arr[0];
for (int i = 1; i < arr.length; i++) {
dp[i] = Math.max(dp[i - 1] + arr[i], arr[i]);//参考dp方程推理过程
ans = Math.max(ans, dp[i]);//找出最大的结果
}
for (int i : dp) {
System.out.print(i + " ");
}
System.out.println();
return ans;
}
}
package dp;
/**
* LeetCode 第 221 号问题:最大正方形。
* 在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。
* 示例:
* 输入:
* 1 0 1 0 0
* 1 0 1 1 1
* 1 1 1 1 1
* 1 0 0 1 0
* <p>
* 输出: 4
*/
public class 最大正方形 {
public static void main(String[] args) {
}
}
package dp;
/**
* https://mp.weixin.qq.com/s?__biz=MzUyNjQxNjYyMg==&mid=2247486923&idx=2&sn=6c1c8aeb4db68522e67ddf8c1e933660&chksm=fa0e624acd79eb5cdb410808921609a830b9b9221e813e4eb89cf551ca48f317668d44b095d2&scene=21#wechat_redirect
* LeetCode 第 64 号问题最小路径和
* 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
* 说明:每次只能向下或者向右移动一步。
* 示例:
* 输入:
* [
* [1,3,1],
* [1,5,1],
* [4,2,1]
* ]
* 输出: 7
* 解释: 因为路径 1→3→1→1→1 的总和最小。
*/
public class 最小路径和 {
public static void main(String[] args) {
int[][] arr = {{1, 3, 1}, {1, 5, 1}, {4, 2, 1}};
System.out.println(zq(arr));
}
/**
* dp[i][j]代表走到第i行,第j列,走过来的最小路径和,
* dp[i][j] = Math.min(dp[i - 1][j] + dp[i][j - 1]) + arr[i][j]
* 该递推方程代表,走到(i,j)的值,应当是(i-1,j)和(i,j-1)之间的较小值
*
* @param arr 该数组
* @return 最小路径和
*/
public static int zq(int[][] arr) {
if (arr.length == 0 || arr[0].length == 0) return 0;
//首先判断数组是不是为空
int m = arr.length, n = arr[0].length;
int[][] dp = new int[m][n];
{//基础条件代码块
dp[0][0] = arr[0][0];
for (int i = 1; i < m; i++) {
dp[i][0] = arr[i][0] + dp[i - 1][0];
}//初始化第一列
for (int i = 1; i < n; i++) {
dp[0][i] = arr[0][i] + dp[0][i - 1];
}//初始化第一行
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + arr[i][j];
}
}
return dp[m - 1][n - 1];
}
}
package dp;
import java.util.Arrays;
/**
* LeetCode 第 62 号问题:机器人走方格
* https://mp.weixin.qq.com/s?__biz=MzUyNjQxNjYyMg==&mid=2247486923&idx=2&sn=6c1c8aeb4db68522e67ddf8c1e933660&chksm=fa0e624acd79eb5cdb410808921609a830b9b9221e813e4eb89cf551ca48f317668d44b095d2&scene=21#wechat_redirect
* 矩阵类动态规划,也可以叫做坐标类动态规划,一般这类问题都会给你一个矩阵,矩阵里面有着一些信息,然后你需要根据这些信息求解问题。
* 其实 矩阵可以看作是图的一种,怎么说?你可以把整个矩阵当成一个图,
* 矩阵里面的每个位置上的元素当成是图上的节点,然后每个节点的邻居就是其相邻的上下左右的位置,
* 我们遍历矩阵其实就是遍历图,在遍历的过程中会有一些临时的状态,也就是子问题的答案,
* 我们记录这些答案,从而推得我们最后想要的答案。
* 给定一个矩阵,问有多少种不同的方式从起点(0,0) 到终点 (m-1,n-1),并且每次移动只能向右或者向下,我们还是按之前提到的分析动态规划那四个步骤来思考一下:
* <p>
* 问题拆解
* 题目中说了,每次移动只能是向右或者是向下,矩阵类动态规划需要关注当前位置和其相邻位置的关系,对于某一个位置来说,经过它的路径只能从它上面过来,或者从它左边过来,
* 因此,如果需要求到达当前位置的不同路径,我们需要知道到达其上方位置的不同路径,以及到达其左方位置的不同路径
* 状态定义
* 矩阵类动态规划的状态定义相对来说比较简单,只需要看当前位置即可,问题拆解中,我们分析了当前位置和 其邻居的关系,提到每个位置其实都可以算做是终点,状态表示就是 “从起点到达该位置的不同路径数目”
* 递推方程
* 有了状态,也知道了问题之间的联系,其实递推方程也出来了,就是
* dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
* 有了这些,这道题还没完,我们还要考虑状态数组的初始化问题,对于上边界和左边界的点,因为它们只能从一个方向过来,需要单独考虑,比如上边界的点只能从左边这一个方向过来,左边界的点只能从上边这一个方向过来,它们的不同路径个数其实就只有 1,提前处理就好。
*/
public class 机器人走方格 {
public static void main(String[] args) {
// System.out.println(Jqr(7, 3));
int[][] arr = new int[3][4];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[0].length; j++) {
if (Math.random() * 15 < 3)
arr[i][j] = 1;
}
}
// int[][] test={{0,0,0},{0,1,0},{0,0,0}};
System.out.println(ZhangAi(arr));
for (int[] ints : arr) {
System.out.println(Arrays.toString(ints));
}
}
/**
* LeetCode 第 63 号问题,机器人走方格
* 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
* 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
* 问总共有多少条不同的路径?
* <p>
* 具体思路:根据走楼梯推理得到:分解为简单的重复子问题,达到最优子结构
* 机器人从左上角到达(m,n),由于只能往右或者往下走,寻找倒数第二步与最后一步的关系
* 倒数第二步,可能走到(m-1,n)或者走到(m,n-1),走到这里再走一步就能到达右下角
* 机器人到达每个点都可以看做终点,由于是路径总数,则dp方程为
* dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
* dp数组语义就是,dp[i][j]代表机器人从左上角走到(i,j)有多少种方式
* 所以基本条件就是,当只有1行的时候,只有一种走法
* 当只有一列的时候也只有一种走法
*
* @param m 长度
* @param n 宽度
* @return 路径总数
*/
public static int Jqr(int m, int n) {
int[][] dp = new int[m][n];
for (int i = 0; i < m; i++) {
dp[i][0] = 1;
}//基本条件:当只有一列的时候,只有一种走法
for (int i = 0; i < n; i++) {
dp[0][i] = 1;
}//基本条件:当只有一行的时候,只有一种走法
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];//数组从0开始
}
/**
* 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
* 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
* 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
* 输入:
* [
* [0,0,0],
* [0,1,0],
* [0,0,0]
* ]
* 输出: 2
* 解释:
* 3x3 网格的正中间有一个障碍物。
* 从左上角到右下角一共有 2 条不同的路径:
* 1. 向右 -> 向右 -> 向下 -> 向下
* 2. 向下 -> 向下 -> 向右 -> 向右
* 在上面那道题的基础上,矩阵中增加了障碍物,这里只需要针对障碍物进行判断即可,
* 如果当前位置是障碍物的话,状态数组中当前位置记录的答案就是0,
* 也就是没有任何一条路径可以到达当前位置,
* 除了这一点外,其余的分析方法和解题思路和之前 一样 。
*
* @param arr 包含障碍的数组
*/
public static int ZhangAi(int[][] arr) {
if (arr.length == 0 || arr[0].length == 0) {
return 0;
}//如果没有网格,m和n都是0,没有输入,直接返回0
if (arr[0][0] == 1) return 0;//如果左上角,第一个网格就是障碍物,那一条路也没有
int m = arr.length, n = arr[0].length;
int[][] dp = new int[m][n];
dp[0][0] = 1;
for (int i = 1; i < m; i++) {
dp[i][0] = arr[i][0] == 1 ? 0 : dp[i - 1][0];//
}//初始化第一列,如果在源数组中该点为1,就说明是障碍,给障碍赋值为0,也就是无法到达
for (int i = 1; i < n; i++) {
dp[0][i] = arr[0][i] == 1 ? 0 : dp[0][i - 1];
}//同理初始化第一行
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = arr[i][j] == 1 ? 0 : dp[i - 1][j] + dp[i][j - 1];
}
}
for (int[] ints : dp) {
System.out.println(Arrays.toString(ints));
}
return dp[m - 1][n - 1];
}
}
......@@ -36,6 +36,12 @@ dp[i]语义就是走i阶楼梯能有多少种选择
大白话:把已知的数据存在数组里,作为基本条件,然后再根据数组语义找出dp方程,
也就是前面得到的答案可以推出后面的答案
矩阵类动态规划,也可以叫做坐标类动态规划,一般这类问题都会给你一个矩阵,矩阵里面有着一些信息,然后你需要根据这些信息求解问题。
其实 矩阵可以看作是图的一种,怎么说?你可以把整个矩阵当成一个图,
矩阵里面的每个位置上的元素当成是图上的节点,然后每个节点的邻居就是其相邻的上下左右的位置,
我们遍历矩阵其实就是遍历图,在遍历的过程中会有一些临时的状态,也就是子问题的答案,
我们记录这些答案,从而推得我们最后想要的答案。
动态规划,在子问题重叠的情况,不同的子问题具有公共的子子问题
动态规划需要具备最优子结构,重叠子问题
基本条件:开始动态规划的,初值,起始条件
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册