牛客竞赛每日俩题 - 动态规划1

简介: 牛客竞赛每日俩题 - 动态规划1

DP入门(存储之前状态以简化)

拆分词句_牛客题霸_牛客网

思路:


方法:动态规划

状态:

       子状态:前1 , 2 , 3 , ...,n 个字符能否根据词典中的词被成功分词

       F(i): 前 i 个字符能否根据词典中的词被成功分词

状态递推:

       F(i): true{j <i && F(j) && substr[j,i-j]能在词典中找到 } OR false

       在j 小于 i 中,只要能找到一个 F(j) 为 true ,并且从 j+1 到 i 之间的字符能在词典

       中找到,则F(i) 为 true

初始值:

       对于初始值无法确定的,可以引入一个不代表实际意义的空状态,作为状态的起始

       空状态的值需要保证状态递推可以正确且顺利的进行,到底取什么值可以通过简单

       的例子进行验证

       F(0) = true

返回结果: F(n)


例如题目样例:


当i==3时 有F[0]==true&&可找到[0,3]中有now,所以canbreak[3]==true;


当i==7时 有F[3]==true&&可找到[3,7]有code,所以canbreak[7]==true;


总结:利用F[i]存之前的状态是否可分割,然后搜索后面有无字符,两者都为true则这个整体可分割

class Solution {
public:
    bool wordBreak(string s, unordered_set<string> &dict) {
        if(s.empty()) return false;
        if(dict.empty()) return false;
        vector<bool> canbreak(s.size()+1,false);
        canbreak[0]=true;
        for(int i=1;i<=s.size();i++)
            for(int j=i-1;j>=0;j--){
                if(canbreak[j]&&dict.find(s.substr(j,i-j))!=dict.end()){
                    // F(i): true{j <i && F(j) && substr[j+1,i]能在词典中找到} OR false
                    canbreak[i]=true; 
                    break;
                }
            }
            return canbreak[s.size()];
    }
};

DP解决最短路问题

三角形_牛客题霸_牛客网

状态:

       子状态:从(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]

返回结果:

       min(F(n-1, i))

方法一:递推法

利用dp算出所有路径,再找最短值

class Solution {
public:
    int minimumTotal(vector<vector<int> > &triangle) {
        if(triangle.empty()) return 0;
        vector<vector<int>> minsum(triangle);
        int line=triangle.size();
        for(int i=1;i<line;i++){
            for(int j=0;j<=i;j++){
                //处理左右边界
                if(j==0) minsum[i][j]=minsum[i-1][j]+triangle[i][j];
                else if(j==i) minsum[i][j]=minsum[i-1][j-1]+triangle[i][j];
                else{//核心操作
                    minsum[i][j]=min(minsum[i-1][j],minsum[i-1][j-1])+triangle[i][j];
                }
            }
        }
        int res=minsum[line-1][0];//找到最后一行的最短步数
        for(int i=1;i<line;i++) res=min(res,minsum[line-1][i]);
        return res;
    }
};

方法二:逆推法


状态:

子状态:

       从(n,n),(n,n-1),...(1,0),(1,1),(0,0) 到最后一行的最短路径和

       F(i,j): 从 (i,j)到最后一行的最短路径和

状态递推:

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

初始值:

       F(n-1,0) = triangle[n-1][0], F(n-1,1) = triangle[n-1][1],..., F(n-1,n-1) = triangle[n-1] [n-1]

返回结果:

       F(0, 0)

class Solution {
public:
    int minimumTotal(vector<vector<int> > &triangle) {
        if(triangle.empty()) return 0;
        vector<vector<int>> minsum(triangle);
        int line=triangle.size();
        // 从倒数第二行开始
        for(int i=line-2;i>=0;i--)
        {
            for(int j=0;j<=i;j++){
                minsum[i][j]=min(minsum[i+1][j],minsum[i+1][j+1])+triangle[i][j];
            }
        }
        return minsum[0][0];
    }
};
相关文章
|
移动开发 Shell
蓝桥杯:2020 国赛 例题:天干地支
蓝桥杯:2020 国赛 例题:天干地支
71 0
|
4月前
蓝桥杯动态规划每日一题
蓝桥杯动态规划每日一题
|
4月前
|
机器人
【LeetCode】--- 动态规划 集训(二)
【LeetCode】--- 动态规划 集训(二)
35 0
|
4月前
【LeetCode】--- 动态规划 集训(一)
【LeetCode】--- 动态规划 集训(一)
29 0
|
5月前
|
C++ 存储
力扣C++|一题多解之数学题专场(1)
力扣C++|一题多解之数学题专场(1)
46 0
力扣C++|一题多解之数学题专场(1)
|
5月前
|
C++ 存储 Serverless
力扣C++|一题多解之数学题专场(2)
力扣C++|一题多解之数学题专场(2)
48 0
力扣C++|一题多解之数学题专场(2)
|
5月前
|
测试技术
题目1444:蓝桥杯2014年第五届真题斐波那契
题目1444:蓝桥杯2014年第五届真题斐波那契
53 0
|
11月前
|
机器学习/深度学习 存储 自然语言处理
蓝桥杯系列3——基础算法
蓝桥杯系列3——基础算法
68 0
|
存储 Windows
牛客竞赛每日俩题 - 动态规划4
牛客竞赛每日俩题 - 动态规划4
|
JavaScript
牛客竞赛每日俩题 - 动态规划3
牛客竞赛每日俩题 - 动态规划3