动态规划 - 路径专题

1.求最短路径和
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.

Note: You can only move either down or right at any point in time.
Example:

Input:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.
class Solution {
public:
    int minPathSum(vector<vector<int>>& grid) {
        if(grid.size() == 0)
            return 0;
        int cols = grid.size();
        int rows = grid[0].size();
        vector<vector<int>> dp(cols,vector<int>(rows,0));
        dp[0][0] = grid[0][0];
        for(int i = 1; i < cols;++i) {
            dp[i][0] = grid[i][0] + dp[i-1][0];
        }
        for(int i = 1; i < rows;++i) {
            dp[0][i] = grid[0][i] + dp[0][i-1];
        }
        
        for(int i =1; i< cols;++i){
            for(int j =1;j < rows;++j){
                dp[i][j] = grid[i][j] + min(dp[i-1][j],dp[i][j-1]);
            }
        }
        return dp[cols-1][rows-1];
    }
};


  1. 求不同路径
    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

How many possible unique paths are there?

Above is a 7 x 3 grid. How many possible unique paths are there?

Note: m and n will be at most 100.

Example:

Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Right -> Down
2. Right -> Down -> Right
3. Down -> Right -> Right
class Solution {
public:
    int uniquePaths(int m, int n) {

        vector<vector<int>> record(n,vector<int>(m, 0));
        for(int i =0;i < n;++i){
                  record[i][0] = 1;
        }
        for(int i =0;i < m;++i){
                record[0][i] = 1;
        }
        for(int i = 1;i < n;++i){
            for(int j =1; j < m;++j){
                record[i][j] = record[i-1][j] + record[i][j-1];
            }
        }
        return record[n-1][m-1];
    }
};


  1. 求不同路径
    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

Now consider if some obstacles are added to the grids. How many unique paths would there be?
Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as `1` and `0` respectively in the grid.

Note: m and n will be at most 100.

Example:

Input:
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:
1. Right -> Right -> Down -> Down
2. Down -> Down -> Right -> Right
class Solution {
public:
    
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        if(obstacleGrid.size() == 0)
            return 0;
        //int *pRecordPath = new int[obstacleGrid.size()*obstacleGrid[0].size()]();
        //for(int i = 0; i < obstacleGrid.size()*obstacleGrid[0].size();++i)          pRecordPath[i] = -1;
        int cols = obstacleGrid.size();
        int rows = obstacleGrid[0].size();
        vector<vector<int>> record(cols,vector<int>(rows, 0));
        for(int i =0;i < cols;++i){
            if(obstacleGrid[i][0] == 0)
                record[i][0] = 1;
            else
                break;
        }
        for(int i =0;i < rows;++i){
            if(obstacleGrid[0][i] == 0)
                record[0][i] = 1;
            else
                break;
        }
        for(int i =1;i < cols;++i){
            for(int j = 1; j < rows;++j){
                if(obstacleGrid[i][j] == 0)
                    record[i][j] = record[i-1][j] + record[i][j-1];
                else
                    record[i][j] = 0;
            }
        }
        
        return record[cols-1][rows-1];
        //return uniquePath(obstacleGrid,0,0,record);
    }
    int uniquePath(const vector<vector<int>>& grid,int col,int row,vector<vector<int>> &pRecord) {
        int cnt = 0;
           if(col == grid.size()-1 && row == grid[0].size()-1 && grid[col][row] == 0)
                return 1;
            else if(col < grid.size() && row < grid[0].size() && grid[col][row] == 0) {
                cnt += uniquePath(grid,col+1,row,pRecord); 
                cnt += uniquePath(grid,col,row+1,pRecord); 
                
                return cnt;
            }
        return 0;
    }
};


  1. 最大子序列和,最大子序列乘积


  1. 单词拆分
    给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。
    说明:
    • 拆分时可以重复使用字典中的单词。
    • 你可以假设字典中没有重复的单词。
输入: s = "leetcode", wordDict = ["leet", "code"]
输出: true
解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。
//brust force
bool wordBreak(string s,vector<string>& Dict,int start){
        if(start == s.length())
            return true;
        for(string a : Dict){
            int len = a.length();
            int end = len + start;
            if(end > s.length())    continue;//return false;
            
            if(s.substr(start,len) == a) {
                if(wordBreak(s,Dict,start+len))
                    return true;
            }
        }
        return false;
    }
    bool wordBreak(string s, vector<string>& wordDict) {
        if(s.size() == 0 && wordDict.size() == 0)
            return true;
        //std::unordered_set<string> Dict;
        set<string> Dict;
        for(int i = 0; i < wordDict.size();++i){
            Dict.insert(wordDict[i]);
        }
        return wordBreak(s,wordDict,0);
        /*vector<int> Check(s.size()+1,0);
        Check[0] = 1;
        for(int i = 1;i <= s.size();++i){
            for(int j = 0; j < i;++j){
                if(Check[j]==1 && Dict.find(s.substr(j,i-j)) != Dict.end() ){
                    Check[i] = 1;
                    break;
                }
            }
        }
        return Check[s.size()]== 1;// ? true : false;
        */
    }
//Dynamic programming
/*
这道题仍然是动态规划的题目,我们总结一下动态规划题目的基本思路。
首先我们要决定要存储什么历史信息以及用什么数据结构来存储信息。
然后是最重要的递推式,就是如从存储的历史信息中得到当前步的结果。
最后我们需要考虑的就是起始条件的值。
接下来我们套用上面的思路来解这道题。
首先我们要存储的历史信息res[i]是表示到字符串s的第i个元素为止能不能用字典中的词来表示,我们需要一个长度为n的布尔数组来存储信息。
然后假设我们现在拥有res[0,...,i-1]的结果,我们来获得res[i]的表达式。
*/
    bool wordBreak(string s, vector<string>& wordDict) {
        if(s.size() == 0 && wordDict.size() == 0)
            return true;
        std::unordered_set<string> Dict;
        for(int i = 0; i < wordDict.size();++i){
            Dict.insert(wordDict[i]);
        }
        vector<int> Check(s.size()+1,0);
        Check[0] = 1;
        for(int i = 1;i <= s.size();++i){
            for(int j = 0; j < i;++j){
                if(Check[j]==1 && Dict.find(s.substr(j,i-j)) != Dict.end() ){
                    Check[i] = 1;
                    break;
                }
            }
        }
        return Check[s.size()]== 1;// ? true : false;
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi阅读 7,448评论 0 10
  • The Inner Game of Tennis W Timothy Gallwey Jonathan Cape ...
    网事_79a3阅读 12,273评论 3 20
  • 1851年,63岁的old fuck叔本华出版了他生前最后一本书(这本书让他终于在晚年获得了现世的声名):《附录与...
    郝显阅读 802评论 3 7
  • 放假几天玩疯了,不愿写作业,却成天吵着缠着我们陪他玩。真的惊讶先生没有发火,先是问我作业都有什么,又找来了纸片、火...
    蓝筹娃娃亲子财商阅读 264评论 0 0
  • 我想讲个爱情故事。 她,生于1931年,她偶然认识了一个年长她1岁的他。那天,是她被家人从学校强行带回家的日子。 ...
    左手趣玩阅读 403评论 0 0