动态规划(详细解释)

算法整理六——动态规划 一、概述 基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。 动态规划算法的有效性依赖于问题本身所具有的两个重要性质:最优子结构、重叠子问题 1、最优子结构:当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。 2、重叠子问题: 在解问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。动态规划算法(自底向上)正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,在以后尽可能多地利用这些子问题的解。 阅读详情

日升时奋斗,日落时自省 

目录

1、Fibonacci

2、字符串分割

3、三角矩阵

4、路径总数

5、最小路径和

6、背包问题

7、回文串分割

8、编辑距离

9、不同子序列

 10、总结


DP定义:

动态规划是分治思想的延伸,通俗一点来说就是大事化小,小事化无的艺术

在将大问题化解为小问题的分治过程中,保存对着些小问题已经处理好的结果,并供后面处理更大规模的问题时直接使用这些结果

动态规划具备了以下三个特点

1.把原来的问题分解成了几个相似的子问题

2.所有的子问题都只需解决一次

3.存储子问题的解

动态规划的本质,是对问题状态的定义和状态转移方程的定义(状态以及状态之间的递推关系)

动态规划问题一般从以下四个角度考虑:

1.状态定义

2.状态间的转移方程定义

3.状态的初始化

4.返回结果

状态定义的要求:定义的状态一定要形成递推关系

适用场景:最大值/最小值 ,可不可行, 是不是,方案个数 

以下用例题来 详细了解动态规划

1、Fibonacci

题目来源于牛客网:斐波那契数列_牛客题霸_牛客网

斐波那契数列,最常了解的方法是递归方法解决问题

 那如果是动规的情况如何处理斐波那契数列,

 代码解析(附加注释):

    public int Fibonacci(int n){
        //初始值
        if(n<=0){
            return 0;
        }
        //申请一个数组 ,保存子问题的解,题目要求从第项开始
        int[] dp=new int[n+1];
        //状态初识化
        dp[0]=0; 
        dp[1]=1;
        for(int i=2;i<=n;i++){
            //状态转移方程
            dp[i]=dp[i-1]+dp[i-2];
        }
        //处理dp动规就是
        return dp[n];
    }

2、字符串分割

题目来源于牛客网:拆分词句_牛客题霸_牛客网

题目描述 :给定一个字符串和一个词典dict ,确定是否可以根据词典中的词分成一个或多个单词

比如给定字符串 s = "leetcode"                词典:  dict=["leet" ,"code"]

给定的字符串可以被分解,并且词典中还是有的能组成s字符串

方法:动态规划

 代码解析(附加注释):

    public boolean wordBreak(String s, Set<String> dict){
        //此处0下标表示的 辅助值  看你需要什么条件才能开始
        boolean[] F=new boolean[s.length()+1]; 
        //初识化F(0) = true   只有初识化后才能走
        F[0]=true;
        for(int i=1;i<=s.length();i++){
            for(int j=i-1;j>=0;--j){
                //F(i) : substr(j+1,i)  进行判定是否能在词典中找到
                //以下也是动态转移方程 :
                if(F[j]&&dict.contains(s.substring(j,i))){
                    F[i]=true;
                    break;
                }
            }
        }
        //因为以上创建对象的时候 动规返回 F[最后一个位置]
        return F[s.length()];
    }

3、三角矩阵

题目来源于牛客网:三角形_牛客题霸_牛客网

题目描述 : 给定一个三角矩阵 ,找出自顶向下的最短路径和,每一步可以移动到下一行的相邻数字,比如给定下面一个三角矩阵,自顶向下的最短路径和

方法:动态规划

状态:子状态:

从(0,0) 到 (1,0),(1,1),(2,0),,,,(n,n)的最短路径和F(i,j),从(0,0)到(i,j)的最短路径和

状态递推(状态转移方程):

F(i,j)=min(F(i-1,j-1),F(i-1,j)+triangle[i][j])

初始值: F(0,0)也就是数组开始位置 triangle[0][0] 

以下是三种情况:并且每种情况都是动态规划的转移方程

 代码解释(附加注释):

    public int minimumTotal(ArrayList<ArrayList<Integer>>  triangle){
        if(triangle.isEmpty()){
            return 0;
        }
        List<List<Integer>> min=new ArrayList<>();
        //将所有数组的开始添加一个 顺序表
        for(int i=0;i<triangle.size();i++){
            min.add(new ArrayList<>());
        }
        min.get(0).add(triangle.get(0).get(0));//将开始位置 添加到最小路径中
        for(int i=1;i<triangle.size();i++){
            //此处使用的一个接收值   其实min[i][j]
            int curSum=0;
            for(int j=0;j<=i;j++){
                if(j==0){
                    //相当于第一种情况解释的是  min[i][j]=min[i-1][j]
                    curSum=min.get(i-1).get(0);
                }
                else if(j==i){
                    //相当于第二种情况解释的是  min[i][j]=min[i-1][j-1]  
                    curSum=min.get(i-1).get(j-1);
                }else{
                    //相当于第三种情况解释的是  min[i][j]=Math.min(min[i-1][j-1],min[i-1][j])
                    curSum=Math.min(min.get(i-1).get(j),min.get(i-1).get(j-1));
                }
                // 以上已经处理好了三种情况  接收最小路径 +  当前值
                min.get(i).add(curSum+triangle.get(i).get(j));
            }
        }
        int size=triangle.size();
        //此处就是最后一行,最后一行也包含了所有相关相关路径 第一个值
        int allmin=min.get(size-1).get(0);
        //将所有值对比  找到最小值
        for(int i=1;i<size;i++){
            allmin=Math.min(allmin,min.get(size-1).get(i));
        }
        return allmin;
    }

4、路径总数

题目来源于牛客网:不同路径的数目(一)_牛客题霸_牛客网

题目描述:

在一个m*n的网格的左上角有一个机器人,机器人在任何时候只能向下或者向右移动,机器人试图到达网格的右下角,有多少可能的路径

动态规划:

 代码解释(附加注释):

    public int uniquePaths(int m,int n){
        List<List<Integer>> pathNum=new ArrayList<>();
        //申请 F(i,j)空间   初始化
        for(int i=0;i<m;i++){
            //将每个顺序表的每个空间再创建顺序表
            pathNum.add(new ArrayList<>());
            //将每列第一个元素都进行 加 1 图解详细 ,仔细观看
            pathNum.get(i).add(1);
        }
        for(int i=1;i<n;i++){
            //将每一列进行加1    也就是第一行进行每个元素+1
            pathNum.get(0).add(1);
        }
        for(int i=1;i<m;i++){
            for(int j=1;j<n;j++){
                //sum(i,j)=sum(i-1,j)+sum(i,j-1)   
                pathNum.get(i).add(pathNum.get(i).get(j-1)+pathNum.get(i-1).get(j));
            }
        }
        //动态规划后 处理结束了 每次走动就是叠加起来
        return pathNum.get(m-1).get(n-1);
    }

5、最小路径和

题目来源于力扣:力扣

题目描述:给定一个m*n的网格 ,网格用非负数填充,找到一条从左上角到右下角的最短路径

注:每次只能向下或者向右移动 ,相当于是路径总数的基础上找到一个最短的路径

方法:动态规划

状态:

子状态: 从(0,0)到达 (1,0),(1,1),(2,1) ...(m-1,n-1)

minsum(i,j):从(0,0) 到达minsum(i,j)的最短路径

状态转移方程:

minsum[i][j]=Math.min(minsum[i-1,j],minsum[i,j-1])+minsum[i][j]

初始化值:

minsum[0][0]=(0,0)

特殊情况:第0行 和 第0列

minsum(0,i)=minsum(0,i-1)+(0,i)

minsum(i,0)=minsum(i-1,0)+(i,0)

 代码解析(附加注释):

    public int minPathSum(int[][] minsum){
        int row=minsum.length;
        int col=minsum.length;
        //如果行还是列有一个为空  返回为0
        if(row==0||col==0){
            return 0;
        }
        //F(0,0) F(0,i) F(i,0) 初始化
        for(int i=1;i<row;i++){
            // 状态初识化值  处理行值
            minsum[i][0]=minsum[i-1][0]+minsum[i][0];
        }
        for(int i=1;i<col;i++){
            // 状态初识化值  处理列值
            minsum[0][i]=minsum[0][i-1]+minsum[0][i];
        }
        //调用状态转移方程:
        // minsum[i][j]=minsum[i][j]+Math.min(minsum[i-1][j],minsum[i][j-1])
        for(int i=1;i<row;i++){
            for(int j=1;j<col;j++){
                minsum[i][j]=minsum[i][j]+Math.min(minsum[i-1][j],minsum[i][j-1]);
            }
        }
        //结束结果  动态规划一步一步处理 二维数组最后结束
        return minsum[row-1][col-1];
    }

6、背包问题

题目来源于炼码:LintCode 炼码

题目描述:

有n个物品和一个大小为m的背包,给定数组A表示每个物品的大小和数组V表示每个物品的价值。

问最多能装下背包的总价值是多大?

 状态:

F(i,j):前i个物品放入大小为 j 的背包中所获得的最大价值

状态转移方程过程:

对于第i个商品,有一种例外,装不下,两种选择,放或者不放,如果装不下:此时的价值与前i-1的个的价值是一样的,表示不装

F(i,j)=F(i-1,j)

如果可以装入,需要在两种选择中找到最大的

F(i,j)=max(F(i-1,j),F(i-1,j-A[i])+V[i])   注:此处看的不是那么清楚,一会看一下图解

F(i-1,j):表示不把第i个物品放入背包中,所以它的价值就是前i-1个物品放入大小为j的背包的最大价值

F(i-1,j-A[i])+V[i] :表示把第i个物品放入背包中,价值增加V[i] ,但是需要腾出 j-A[i]的大小放第i个商品

初始化:第0行 和第0列都为0 表示没有装物品的价值都为0

 代码解析(附加注释):

    public int backPackII(int m,int[] A,int[] V){
        int num=A.length;
        if(m==0||num==0){
            return 0;
        }
        //需要辅助值 作为准备  数组中 num+1 表示 物品大小 m+1 表示价值
        int[][] maxValue=new int[num+1][m+1];
        //初始化所有位置为0  第一行 和 第一列都为0 初识条件
        for(int i=0;i<=num;i++){
            maxValue[i][0]=0;
        }
        for(int i=1;i<=m;i++){
            maxValue[0][i]=0;
        }
        for(int i=1;i<=num;i++){
            for(int j=1;j<=m;j++){
                //第i个商品在A中对应的索引为 i-1 i从1开始
                //如果第i个商品大于j 说明放不下 所以(i,j)的最大价值 和 (i-1,j)相同
                if(A[i-1]>j){
                    //当前物品体积  大于  当前容量 就说明装不下,把原来的继承下来就行
                    maxValue[i][j]=maxValue[i-1][j];
                }else{
                    //如果可以装下,分两情况 装或者不装
                    //如果不装 ,即为 (i-1,j)
                    //如果装 , 需要腾出放第i个物品大小的空间:j-A[i-1],能装之后的最大价值即为原有价值加上
                    // maxValue[i - 1][j - A[i - 1]]   +  V[i-1]
                    //最后在装与不装中选出最大的价值
                    int newValue=maxValue[i-1][j-A[i-1]]+V[i-1];
                    //新值 与  原来值   进行比对
                    maxValue[i][j]=Math.max(newValue,maxValue[i-1][j]);
                }
            }
        }
        return maxValue[num][m];
    }

注:newValue=maxValue[i-1][j-A[i-1]]+V[i-1];  创建数组时就已经了各加一个空间,第0行和第0列已经处理好了,占了一个位置,所以V[i-1]其实也就是V[i],因为二维数组整体加1如果还想要调用V[i] 此处就需要V[i-1]

7、回文串分割

题目来源于牛客网:分割回文串-ii_牛客题霸_牛客网

回文串:正读和反读都一样的字符串,比如level,noon字符串左右对称

题目描述:

给定一个字符串 s, 把 s 分割成一系列的子串,分割的每一个子串都为回文串返回最小的分割次数比如,给定 s="abb" 返回1 ,因为一次 cut 就可以产生回文分割[“a","bb"];

方法:动态规划

状态:

子状态:到 1,2,3,....n个字符需要的最小分割数

F(i):到第i个字符需要的最小分割数

状态递推(状态转移方程):

F(i) =min(F(i),1+F(j)) ,     F(i) 表示第i个字符需要的最小分割数, 就 j  <  i && j+1 到 i是回文串上式表示如果从j+1 到i 判断 为回文字符串,且已经知道从第 1 个字符串到第 j 个字符的最小切割数,那么只需要再切一次 ,就可以保证 1到j ,  j+1 到 i都为回文串

初始化 : 

F(i) =i-1  表示最大切割数 : 单个字符需要切0次 ,因为单子符都为回文串(图解)

代码解释(附加注释):

    public int mincut(String s){
        int len = s.length();
        if(len==0){
            return 0;
        }
        //进行 判定该阶段的字符串 是不是 回文串
        boolean[][] Mat=getMat(s);
        int[] mincut=new int[len+1];
        //F(i) 初始化
        //F(0)=-1 必要项 如果没有这一项 ,对于 重叠字符串 “aaaa" 会产生错误的结果
        for(int i=0;i<=len;i++){
            mincut[i]=i-1;   //此处针对特殊情况  就是全部字符串都是重复的 ,应对错失
        }
        for(int i=1;i<=len;i++){
            for(int j=0;j<i;j++){
                //F(i)=min(F(i),1+F(j))
                //从最长串判断 如果从第j+1 到 i为回文字符串
                //则再加一次分割 从 1 到 j ,j+1 的 i 的字符就全部分成了回文字符串
                if(Mat[j][i-1]){
                    mincut[i]=Math.min(mincut[i],mincut[j]+1);
                }
            }
        }
        return mincut[len];
    }
    //数组包装 回文串判定
    private boolean[][] getMat(String s) {
        int len =s.length();
        //二维数组 表示 字符串的前后
        boolean[][] Mat=new boolean[len][len];
        for(int i=len-1;i>=0;i--){
            //到这开始 从一个一个来
            for(int j=i;j<len;j++){
                //从当前位置开始 向后判断
                if(j==i){
                    //处理单个字符  单个字符串都是回文串
                    Mat[i][j]=true;
                }else if(j==i+1){  //判断相邻情况
                    //相邻字符如果相同 则为回文字符串
                    if(s.charAt(i)==s.charAt(j)){
                        Mat[i][j]=true;
                    }else{
                        //如果不是相邻字符串  返回为 false
                        Mat[i][j]=false;
                    }
                }else{
                    //F(i,j)=(s[i]==s[j]&&F(i+1,j-1))
                    //F(i+1,j-1) 基本表示这个意思 l     eve       l
                    Mat[i][j]=(s.charAt(i)==s.charAt(j)&&Mat[i+1][j-1]);
                }
            }
        }
        return Mat;
    }

8、编辑距离

题目来源于牛客网:编辑距离_牛客题霸_牛客网

题目描述: 给定两个单词word1 和 word2、 找到最小的修改步数 ,把word1 转换成 word2,每一个操作记为一步 ,允许在一个word上进行如下3种操作:

(1)插入一个字符

(2)删除一个字符

(3)替换一个字符

编辑距离 是指两个字符串之间, 由一个转成另一各所需的最少编辑操作次数

方法: 动态规划 

状态:

子状态 :word 1的前1,2,3,....m个字符转换成word2的前1,2,3,....n个字符需要的编辑距离

F(i,j):word1的前i个字符于word2 的前j个字符的编辑距离

状态递推(状态转移方程):

F(i,j) =min(F(i-1,j)+1,F(i,j-1)+1,F(i-1,j-1)+(word1[i]==word2[j]?0:1))  注: 此处下面再解释

上式表示从删除,增加和替换操作中选择一个最小操作数

F(i-1,j):word1[1...i-1]于word2[1....j]的编辑距离 ,删除word1[i]的字符--->F(i,j)

F(i,j-1):word1[1....i]于word2[1....j-1]的编辑距离,增加一个字符--->F(i,j)

F(i-1,j-1):word1[1....i-1]于word2[1...j-1]的编辑距离 ,如果word1[i]与word2[j]相同,不做任何操作 ,编辑距离不变,如果word1[i]与word2[j]不同,替换word1[i]的字符为word2[j]--->F(i,j)

初始化:

初始化一定要是确定的值,如果这里不加入空串,初始值无法确定

F(i,0)=i :word 与空串的编辑距离 ,删除操作

F(0,i)=i: 空串与word的编辑距离 ,增加操作

放回结果:F(m,n) (图解没有完全 以下给出 可以找到规律)

 代码注释(附加注释):

    //word 与空串 之间的编辑距离为word 的长度
    public int minDistance(String word1,String word2){
        if(word1.isEmpty()||word2.isEmpty()){
            return Math.max(word1.length(),word2.length());
        }
        int len1=word1.length();
        int len2=word2.length();
        //动态规划 需要辅助值 所以当前数组也多创建了一行
        int[][] minDis=new int[len1+1][len2+1];
        //F(i,j) 初始化 针对不同位置的东西
        for(int i=0;i<=len1;i++){
            minDis[i][0]=i;
        }
        for(int i=0;i<=len2;i++){
            minDis[0][i]=i;
        }
        for(int i=1;i<=len1;i++){
            for(int j=1;j<=len2;j++){
                //F(i,j) =min (F(i-1,j)+1,F(i,j-1)+1,F(i-1,j-1)+(word1[i]=word2[j]?0:1))
                minDis[i][j]=Math.min(minDis[i-1][j],minDis[i][j-1])+1;
                if(word1.charAt(i-1)==word2.charAt(j-1)){
                    //字符相等 F(i-1,j-1) 编辑距离不变  与上次
                    minDis[i][j]=Math.min(minDis[i][j],minDis[i-1][j-1]);
                }else{
                    //字符不相等 F(i-1,j-1) 编辑距离+1
                    // 因为不同 所以 当前位置的 与  上一位置+1 进行比较
                    minDis[i][j]=Math.min(minDis[i][j],minDis[i-1][j-1]+1);
                }
            }
        }
        return minDis[len1][len2];
    }

9、不同子序列

题目来源于牛客网:不同的子序列_牛客题霸_牛客网

题目描述: 给定两个字符串S 和 T ,求S有多少个不同的子串 与T相同。S的子串定义为 S中任意去掉0个或者多个字符形成的串 子串可以不连续 ,但是相对位置不能变。

比如“ACE” 是“ABCDE” 的子串 ,但是“AEC” 不是

问题处理:S有多少个不同的子与T相同的个数

S[1:m] 中的子串与T[1:n]相同的个数 由S的前m个字符组成的子串与T的前n个字符相同的个数

状态:

子状态:由S的前1,2....m个字符组成的子串与T前1,2,.....n个字符相同的个数F(i,j):S[1;i]中的子串与T[1:j]相同的个数

在F(i,j):S[1:i]中的子串与T[1:j]相同的个数

状态递推(状态转移方程):

在F(i,j),处需要考虑S[i]=T[j]和S[i]!=T[j]这两种情况

当S[i]=T[j]:

1> :让S[i]匹配T[j],则F(i,j)=F(i-1,j-1) 

2> :让S[i]不匹配 T[j] ,则问题就变为S[1:i-1] 中的子串与T[1:j]相同的个数 ,则F(i,j)=F(i-1,j)

故:S[i]=T[j]时,F(i,j)=F(i-1,j-1)+F(i-1,j)

当S[i]!=T[j]

问题退化为 s[1:i-1] 中的子串 与 T[1:j] 相同的个数

故,S[i]!=T[j] 时 F(i , j) =F(i-1,j)

初始化 :引入空串进行初始化 

F(i,0)=1 -->S的子串与空串相同的个数 ,只有空串 与 空串相同

 代码解析(附加注释):

    public int numDistinct(String s,String T){
        int slen=s.length();
        int tlen=T.length();
        int[][] numDis=new int[slen+1][tlen+1];
        numDis[0][0]=1;
        //F(i,j) 初始化第一行 剩余列的所有值为0
        for(int i=1;i<=tlen;i++){
            numDis[0][i]=0;
        }
        //F(i,0)=1   辅助值 
        for(int i=1;i<=slen;i++){
            numDis[i][0]=1;
        }
        //每次都从1 开始 因为多创建一个空间 作为辅助值来提供帮助
        for(int i=1;i<=slen;i++){
            for(int j=1;j<=tlen;j++){
                //s 的第i个字符与 T 的第j个字符相同
                if(s.charAt(i-1)==T.charAt(j-1)){
                    numDis[i][j]=numDis[i-1][j]+numDis[i-1][j-1];
                }else{
                    // s 的第i个字符与 T 的第j个字符不相同
                    //从S 的前 i-1 个字符中找子串 ,使子串 与 T的前j个字符相同
                    numDis[i][j]=numDis[i-1][j];
                }
            }
        }
        return numDis[slen][tlen];
    }

 10、总结

动态规划 其实与贪心思想有点相似,都需要自己去看是否有规律可循。

(1)状态定义:其实就是设计动态规划的问题是啥

(2)状态转移方程:将文字定义来的状态转化为一个代码方程表示

(3)状态初始值  辅助值 是动态规划的起步 (根据动态方程来决定如何启动)

动态规划(Dynamic programming)详解 动态规划(Dynamic programming,简称DP)是一种将复杂问题分解成很多子问题,并将子问题的求解结果存储起来避免重复求解的一种算法。动态规划一般用来解决最优问题。而解决问题的过程,需要经历多个决策阶段。每个决策阶段都对应着一组状态。最后通过一组决策序列(动态转移方程),产生最终期望的最优解。 能用动态规划解决的问题,需要满足三个条件:最优子结构,无后效性和子问题重叠。 阅读详情

相关推荐

【动态规划】动态规划的详细进行解释,包含代码

dp[i][w]:表示前i个物品,背包容量为w时的最大价值。:表示和的最长公共子序列的长度。动态规划是一种非常强大的算法设计技巧,适用于许多具有重叠子问题和最优子结构的问题。通过将大问题拆解为更小的子问题,动态规划可以显著减少计算复杂度,尤其适合解决优化问题,如最短路径、背包问题、子序列问题等。定义好状态。找到正确的状态转移方程。有效地使用存储结构来避免重复计算。通过实现不同的动态规划问题,我们可以更深入地理解如何应用这些技巧来解决复杂的问题。

wq6qeg88的博客 1326

算法-动态规划 Dynamic Programming--从菜鸟到老鸟

前言最近在牛客网上做了几套公司的真题,发现有关动态规划(Dynamic Programming)算法的题目很多。相对于我来说,算法里面遇到的问题里面感觉最难的也就是动态规划(Dynamic Programming)算法了,于是花了好长时间,查找了相关的文献和资料准备彻底的理解动态规划(Dynamic Programming)算法。一是帮助自己总结知识点,二是也能够帮助他人更好的理解这个算法。后面的参

有图有真相 48万+

动态规划刷题(2)之杨辉三角(详细解释)

动态规划(Dynamic Programming,DP)是一种解决问题的算法思想,通常用于优化重叠子问题的递归算法。DP算法的核心思想是将原问题分解为相互重叠的子问题,并且将子问题的解存储起来,以便以后解决相同的子问题时可以直接使用已知的解,从而避免重复计算。

2301_77523055的博客 1191

【算法】动态规划(Dynamic Programming)

文章目录什么是动态规划算法数字三角形经典递归解法 什么是动态规划算法 总体思想 (1)动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题 (2)经分解得到的子问题往往不是互相独立的,有些子问题被重复计算多次 (3)如果能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量重复计算,从而得到多项式时间算法(备忘录法) (4)图解: 使用动态规划来求解的问题需要具备的基本要素包括: (1)重复子问题 递归算法求解问题时,每次产生的子问题并不总是新问题,有些子

高朗的博客 4万+

动态规划算法详解

动态规划算法通常用于求解具有最优性质的问题 基本概念 动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移。一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划(DP)。 基本思想与策略 基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。...

m0_54615144的博客 2万+

SAP PS项目结算实操:从CJ20N到CJ88,手把手搞定项目成本结转与凭证生成

本文详细解析SAP PS项目结算全流程,从CJ20N到CJ88的操作要点,涵盖成本归集、结算规则配置、结果分析及凭证生成等关键环节。特别针对FICO模块中的项目凭证流转问题提供实战解决方案,帮助财务人员规避常见配置错误,提升项目结算效率与准确性。

weixin_26833503的博客 811

动态规划【DP】详细解释

动态规划算法的复杂度和空间利用率很高,适用于求解一些比较复杂的最优化问题,例如背包问题、最长递增子序列问题、编辑距离问题等。无后效性:状态只与其之前的状态有关,和之后的状态无关。这种性质被称作“无后效性”,即在求解阶段,我们不必关心状态是如何转移过来的,只需要关注现在的状态和后续状态。(除去起点)中的所有点恰好一次,回到起点的最小代价,通过循环方式依次求出每一个状态并存储它的最小代价值,最终返回从起点出发,经过点集。好的,再举一个十分复杂的例子,以解决旅行家问题为例子,我们来详细介绍动态规划的思想和步骤。

Chey_LER_SLC的博客 2232

Claude Code vs Codex

Claude Code 提供了一个生产就绪(production-ready)的实现,包含良好的错误处理、优雅的关闭逻辑、详细注释和文档,以及内置测试。Claude Code 输出了一个可运行的 Next.js + TypeScript 前端,但错过了一些设计里的黄色主题元素;Codex 则生成自己的版本,没有导出设计中的图片,也没严格遵照设计主题。Codex 完成同样功能,但更简洁直接,文档和注释少一些但功能达标。任务都用同样的提示,使用 TypeScript 实现,并在一天内完成。

weixin_49869937的博客 2382

动态规划详细解释

动态规划(Dynamic Programming,简称DP)是一种用于解决复杂问题的算法思想,特别适用于具有重叠子问题和最优子结构性质的问题。它通过将问题分解为更小的子问题,并保存这些子问题的解以避免重复计算,从而提高算法的效率。动态规划通常用于优化问题,如最短路径、最长公共子序列、背包问题等。重叠子问题(Overlapping Subproblems):最优子结构(Optimal Substructure):状态(State):状态转移方程(State Transition Equation):定义状态:

公孙莫言的博客 1297

【图像大模型】RIFE实战:如何通过中间流估计实现4K视频的实时插帧优化

本文深入解析了基于深度学习的RIFE视频插帧算法,重点探讨其核心的中间流估计技术如何实现高效精准的帧生成。通过实战教程,详细介绍了针对4K视频的实时处理优化方案,包括环境配置、参数调优及性能瓶颈分析,帮助用户利用消费级显卡将低帧率视频转化为流畅的高帧率体验。

weixin_29093017的博客 454

5060TI显卡深度学习环境搭建:CUDA12.8与CUDNN9.8.0的完美搭配

本文详细介绍了在Win10系统下为5060TI显卡搭建深度学习环境的最佳实践,重点配置CUDA12.8与CUDNN9.8.0的完美组合。通过优化OpenCV编译选项和YOLOv5环境设置,显著提升模型训练和推理效率,帮助开发者充分发挥5060TI显卡的性能潜力。

weixin_29065791的博客 486

关于动态规划的详细解释

https://www.cnblogs.com/wuyuegb2312/p/3281264.html 上面的链接给的是详细的动态规划例子与讲解,美中不足的是对于字符串相似度,也就是编辑距离这里讲的不是太明白,然后在下面的这篇文章中得到了很好的解释。 https://www.cnblogs.com/xiaoyulong/p/8846745.html...

少游 244

国产系统迁移实战:在银河麒麟V10上搞定Wine32位支持,让老Windows软件跑起来

本文详细介绍了在银河麒麟V10操作系统上构建Wine32位支持的全过程,帮助用户解决Windows应用迁移难题。从系统架构差异分析到Wine环境配置,再到实战应用部署与优化,提供了一套完整的解决方案,确保老Windows软件在国产系统上稳定运行。

weixin_32288959的博客 648

动态规划(详细解释,从入门到实践,逐步讲解)

首先,我们看一下官方定义:定义: 动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各...

游戏开发、游戏引擎开发、逆向破解爱好者 739

劳特巴赫 Trace32 调试使用教程

详细介绍如何使用trace32进行调试

m0_56208280的博客 4万+

R语言dplyr包recode函数、recode_factor函数数值或因子替换实战

R语言dplyr包recode函数、recode_factor函数数值或因子替换实战 目录 R语言dplyr包recode函数、recode_factor函数数值或因子替换实战 #导入dplyr包 #recode函数进行数值替换 #recode_factor函数对因子变量进行替换 #导入dplyr包 install.packages("dplyr") # Install & load dplyr library("dpl.

data+scenario+science+insight 1588

经典中的经典算法:动态规划(详细解释,从入门到实践,逐步讲解)

动态规划的重要性就不多说,直接进入正题 首先,我们看一下官方定义:定义: 动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。 动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。基本思想与策略编辑: 由于动态

Jiguoyuanyic的博客 4万+

Android AICore的核心组件工作原理解析

AICore通过LoRA实现个性化适配Gemini Nano提供多模态智能Safety Features保障可信运行,构建了端侧AI的完整生态。这种设计不仅让手机等移动设备能处理复杂AI任务(如实时多模态交互),还通过隐私保护机制打破了传统云端AI的数据依赖,为未来“设备即AI基础设施”的愿景奠定了基础。输入触发:用户输入“刚提交了代码,等审核”→ 进入TEE加密处理。Gemini Nano基础生成:通过原始权重W_q生成初始回复候选。LoRA个性化微调:通过A'和B'计算ΔW,更新W_q。

1550

01背包问题 动态规划求解方法 动态方程的详细解释 能理解的解释(附python代码)

01背包问题属于组合优化问题:假设你要出门旅游,你现在有一个书包,这个书包的容量(capacity)有限,有很多物品如牙刷、防晒霜、雨伞、水杯等等,但书包装不下所有物品,因此我们必须有所取舍。那么通常我们怎么取舍的呢?一般我们会选择那些重要的物品,这个重要性我们可以量化为一个数字(value)。此时背包问题就抽象为: 给定n个物品,容量为capacity的背包。每个物品自身体积ws=[w1, w...

qq_31713935的博客 972

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

动态规划和强化学习的关系,以及优缺点比较。请详细进行解释

Bellman方程是动态规划和强化学习中至关重要的工具,提供了一种递归关系来描述状态或状态-动作对的价值。通过Bellman方程,智能体可以计算最优策略或最优值函数,并逐步逼近最优解。它的核心思想是将复杂的多阶段决策问题分解成一个个简单的子问题,利用递归关系求解。

wq6qeg88的博客 1915

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

【leetcode】97. Interleaving String【java】动态规划,并有详细解释

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: s1 = "aabcc", s2 = "dbbca", When s3 = "aadbbcbcac", return true. When s3 = "aadbbbaccc", r

陈善亮的博客 1205

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

动态数组怎么定义_经典中的经典算法,动态规划(详细解释,从入门到实践,逐步讲解)...

动态规划的重要性就不多说,直接进入正题首先,我们看一下官方定义:定义:动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的...

weixin_39766910的博客 175
上一篇: 贪心算法(例题详细解说)
下一篇: 回溯算法(例题详细解析)
学习自省
博客等级 码龄5年 284粉丝 101原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值