【算法提高:动态规划】1.1 数字三角形模型

文章目录

  • 例题列表
    • [1015. 摘花生](#1015. 摘花生)
    • [1018. 最低通行费](#1018. 最低通行费)
    • [1027. 方格取数(两条路径同时走)⭐⭐⭐⭐⭐](#1027. 方格取数(两条路径同时走)⭐⭐⭐⭐⭐)
    • [275. 传纸条(转换成 两条路径同时走)](#275. 传纸条(转换成 两条路径同时走))

例题列表

1015. 摘花生

https://www.acwing.com/problem/content/1017/

状态要么从左转移过来,要么从上转移过来。

java 复制代码
import java.io.BufferedInputStream;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sin = new Scanner(new BufferedInputStream(System.in));
        int t = sin.nextInt();
        while (t-- != 0) {
            int r = sin.nextInt(), c = sin.nextInt();
            int[][] g = new int[r][c];
            for (int i = 0; i < r; ++i) {
                for (int j = 0; j < c; ++j) {
                    g[i][j] = sin.nextInt();
                }
            }
            for (int i = 0; i < r; ++i) {
                for (int j = 0; j < c; ++j) {
                    int pre = 0;
                    if (i > 0) pre = Math.max(pre, g[i - 1][j]);
                    if (j > 0) pre = Math.max(pre, g[i][j - 1]);
                    g[i][j] += pre;
                }
            }
            System.out.println(g[r - 1][c - 1]);
        }
    }
}

1018. 最低通行费

https://www.acwing.com/problem/content/1020/

不要被题目的商人必须在 ( 2 N − 1 ) (2N−1) (2N−1) 个单位时间穿越出去。

其实就是说商人必须往右走或者往下走。

java 复制代码
import java.io.BufferedInputStream;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sin = new Scanner(new BufferedInputStream(System.in));
        int n = sin.nextInt();
        int[][] a = new int[n][n];
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                a[i][j] = sin.nextInt();
            }
        }

        for (int i = 1; i < n; ++i) a[i][0] += a[i - 1][0];
        for (int i = 1; i < n; ++i) a[0][i] += a[0][i - 1];

        for (int i = 1; i < n; ++i) {
            for (int j = 1; j < n; ++j) {
                a[i][j] += Math.min(a[i - 1][j], a[i][j - 1]);
            }
        }
        System.out.println(a[n - 1][n - 1]);
    }
}

dp 数组和原始数据数组可以复用。

1027. 方格取数(两条路径同时走)⭐⭐⭐⭐⭐

https://www.acwing.com/problem/content/1029/

第一想法是贪心的,先走一遍 dp,再走一遍 dp。但是后来发现不对,暂时最优未来不一定最优

让两个路径同时移动,无非就是 4 种情况,就对应着 4 种状态转移。

k 表示走了几步,i1 和 i2 是两个路径到达的横坐标。

java 复制代码
import java.io.BufferedInputStream;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sin = new Scanner(new BufferedInputStream(System.in));
        int n = sin.nextInt();
        int[][] m = new int[n + 1][n + 1];
        while (true) {
            int a = sin.nextInt(), b = sin.nextInt(), c = sin.nextInt();
            if (a == 0 && b == 0 && c == 0) break;
            m[a][b] = c;
        }
        int[][][] dp = new int[2 * n + 1][n + 1][n + 1];
        for (int k = 2; k <= n + n; ++k) {
            // (i1,j1) (i2,j2) 是两条路线到达的位置
            for (int i1 = 1; i1 <= n; ++i1) {
                for (int i2 = 1; i2 <= n; ++i2) {
                    int j1 = k - i1, j2 = k - i2;
                    if (j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n) {
                        int t = m[i1][j1];
                        if (i1 != i2) t += m[i2][j2];
                        
                        // 四种路线选择
                        dp[k][i1][i2] = Math.max(dp[k][i1][i2], dp[k - 1][i1 - 1][i2 - 1] + t);
                        dp[k][i1][i2] = Math.max(dp[k][i1][i2], dp[k - 1][i1 - 1][i2] + t);
                        dp[k][i1][i2] = Math.max(dp[k][i1][i2], dp[k - 1][i1][i2 - 1] + t);
                        dp[k][i1][i2] = Math.max(dp[k][i1][i2], dp[k - 1][i1][i2] + t);
                    }
                }
            }
        }
        System.out.println(dp[n + n][n][n]);
    }
}

275. 传纸条(转换成 两条路径同时走)

https://www.acwing.com/problem/content/277/

这道题和上一道题其实是一样的。

java 复制代码
import java.io.BufferedInputStream;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sin = new Scanner(new BufferedInputStream(System.in));
        int m = sin.nextInt(), n = sin.nextInt();
        int[][] a = new int[m + 1][n + 1];
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                a[i][j] = sin.nextInt();
            }
        }

        int[][][] dp = new int[m + n + 1][m + 1][m + 1];
        for (int k = 2; k <= m + n; ++k) {
            for (int i1 = 1; i1 <= m; ++i1) {
                for (int i2 = 1; i2 <= m; ++i2) {
                    int j1 = k - i1, j2 = k - i2;
                    if (j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n) {
                        int t = a[i1][j1];
                        if (i1 != i2) t += a[i2][j2];

                        dp[k][i1][i2] = Math.max(dp[k][i1][i2], dp[k - 1][i1 - 1][i2] + t);
                        dp[k][i1][i2] = Math.max(dp[k][i1][i2], dp[k - 1][i1 - 1][i2 - 1] + t);
                        dp[k][i1][i2] = Math.max(dp[k][i1][i2], dp[k - 1][i1][i2 - 1] + t);
                        dp[k][i1][i2] = Math.max(dp[k][i1][i2], dp[k - 1][i1][i2] + t);
                    }
                }
            }
        }
        System.out.println(dp[m + n][m][m]);
    }
}
相关推荐
百度Geek说39 分钟前
第一!百度智能云领跑视觉大模型赛道
算法
big_eleven1 小时前
轻松掌握数据结构:二叉树
后端·算法·面试
big_eleven1 小时前
轻松掌握数据结构:二叉查找树
后端·算法·面试
CoovallyAIHub1 小时前
农田扫描提速37%!基于检测置信度的无人机“智能抽查”路径规划,Coovally一键加速模型落地
深度学习·算法·计算机视觉
kyle~2 小时前
OpenCV---特征检测算法(ORB,Oriented FAST and Rotated BRIEF)
人工智能·opencv·算法
初学小刘2 小时前
决策树:机器学习中的强大工具
算法·决策树·机器学习
山顶风景独好2 小时前
【Leetcode】随笔
数据结构·算法·leetcode
lxmyzzs4 小时前
【图像算法 - 16】庖丁解牛:基于YOLO12与OpenCV的车辆部件级实例分割实战(附完整代码)
人工智能·深度学习·opencv·算法·yolo·计算机视觉·实例分割
wow_DG4 小时前
【C++✨】多种 C++ 解法固定宽度右对齐输出(每个数占 8 列)
开发语言·c++·算法
Epiphany.5565 小时前
c++最长上升子序列长度
c++·算法·图论