坐标型\序列型\划分型动态规划
2021/4/17 10:25:50
本文主要是介绍坐标型\序列型\划分型动态规划,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
坐标型动态规划
- 最简单的动态规划
- 给定一个序列或网络
- 需要找到序列中某个/些子序列或网格中的某条路径
– 某种性质最大/最小
– 计数
– 存在性 - 动态规划方程f[i]中的下标i表示以ai为结尾的满足条件的子序列的性质,f[i][j]中的下标i,j表示以格子(i,j)为结尾的满足条件的路径的性质
– 最大值/最小值
– 个数
– 是否存在 - 坐标型动态规划的初始条件f[0]就是指以a0为结尾的子序列的性质
对于网格上的动态规划,如果f[i][j]只依赖于本行的f[i][x]和上一行的f[i-1][y],则可以采用滚动数组的方法压缩空间。
例 洛谷p1002过河卒
https://www.luogu.com.cn/problem/P1002
public class P1002 { public static void main(String[] args) { int[] hx = {1,2,2,1,-1,-2,-2,-1}; int[] hy = {-2,-1,1,2,2,1,-1,-2}; boolean[][] hourse = new boolean[30][30]; long [][] ans = new long [30][30]; int n,m,x,y; Scanner in = new Scanner(System.in); n = in.nextInt(); m = in.nextInt(); x = in.nextInt(); y = in.nextInt(); n+=2; m+=2; x+=2; y+=2; hourse[x][y] = true; for(int i=0;i<8;i++){ hourse[x+hx[i]][y+hy[i]] = true; } ans[2][1] = 1; for(int i=2;i<=n;i++){ for(int j=2;j<=m;j++){ if(hourse[i][j]) continue; else ans[i][j] = ans[i][j-1] + ans[i-1][j]; } } System.out.print(ans[n][m]); } }
序列型动态规划
- 给定一个固定的序列,通常要求求某一个最小数、方式数、可行性等。
- 常常会伴随多种状态。
- f[i]表示前i个元素的某种性质,f[0]表示空序列。
例 领扣515.房屋染色
https://www.lintcode.com/problem/515/
public class P515 { /** * @param costs: n x 3 cost matrix * @return: An integer, the minimum cost to paint all houses */ public int minCost(int[][] costs) { // write your code here int n = costs.length; int[][] f = new int[n+1][3]; for(int i=1; i<=n; i++){ for(int j=0; j<3; j++){ f[i][j] = Integer.MAX_VALUE; for(int k=0; k<3; k++){ if(k==j){ continue; }else{ f[i][j] = Math.min(f[i-1][k]+costs[i-1][j], f[i][j]); } } } } int res = f[n][0]; if(res>f[n][1]) res = f[n][1]; if(res>f[n][2]) res = f[n][2]; return res; } }
划分型动态规划
- 要求将一个序列或字符串划分成若干满足要求的片段
从满足划分条件的最后一个片段开始考虑问题。
例 领扣 108.分割回文串
https://www.lintcode.com/problem/108/
如果段数不固定,则用f[i]表示前i个元素分段后的某种性质
public class P108 { /** * @param s: A string * @return: An integer */ public int minCut(String s) { // write your code here int n = s.length(); if(n == 0 || n == 1) return 0; boolean[][] isHw = new boolean[n][n]; int[] f = new int[n+1]; for(int i=0; i<n; i++){ int l,r; l = i; r = i+1; while(l>=0 && r<n && s.charAt(l)==s.charAt(r)){ isHw[l][r] = true; l--; r++; } r=l=i; while(l>=0 && r<n && s.charAt(l)==s.charAt(r)){ isHw[l][r] = true; l--; r++; } } for(int i=1; i<=n; i++){ f[i] = Integer.MAX_VALUE; for(int j=0; j<i; j++){ if(isHw[j][i-1]==true && f[j]+1 < f[i]){ f[i] = f[j]+1; } } } return f[n]-1; } }
例 领扣 437.书籍复印
当题目指定段数时,用f[i][j]表示前i个元素分段后的某种性质
https://www.lintcode.com/problem/437/
public class P437 { /** * @param pages: an array of integers * @param k: An integer * @return: an integer */ public int copyBooks(int[] pages, int k) { // write your code here int len = pages.length; if(len == 0) return 0; if(k > len) k = len; int[][] f = new int[k+1][len+1]; for(int i=1 ;i<=len; i++){ f[0][i] = Integer.MAX_VALUE; } for(int i=1; i<=k; i++){ for(int j=1; j<=len; j++){ f[i][j] = Integer.MAX_VALUE; int sum = 0; for(int n=j; n>=0; n--){ f[i][j] = Math.min(f[i][j], Math.max(f[i-1][n], sum)); if(n>0){ sum += pages[n-1]; } } } } return f[k][len]; } }
这篇关于坐标型\序列型\划分型动态规划的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26手写消息中间件:从零开始的指南
- 2024-11-26Java语音识别项目资料:新手入门教程
- 2024-11-26JAVA语音识别项目资料:新手入门教程
- 2024-11-26Java语音识别项目资料:入门与实践指南
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料入门教程
- 2024-11-26Java云原生资料:新手入门教程
- 2024-11-25Java创意资料:新手入门的创意学习指南
- 2024-11-25JAVA对接阿里云智能语音服务资料详解:新手入门指南
- 2024-11-25Java对接阿里云智能语音服务资料详解