五月集训(第28天)—动态规划

动态规划

1. 70. 爬楼梯

    思路:
        到达第n层的方法可以是,从第n-1层走一步,或者从n-2层走两步,所以状态方程为f[n] = f[n - 1] + f[n - 2];

class Solution {
public:
    int climbStairs(int n) {
        int f[50], i;
        memset(f, 0, sizeof(f));
        f[1] = 1;
        f[2] = 2;
        for (i = 3; i <= n; ++i) {
            f[i] = f[i - 1] + f[i - 2];
        }
        return f[n];
    }
};

2. 53. 最大子数组和

    思路:
        统计出以i为结尾的最大连续子数组的和。当dp[i - 1] < 0,dp[i] = nums[i]。否则,dp[i] = dp[i - 1] + nums[i]

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int nums_size = nums.size();
        int dp[nums_size];
        int ans = nums[0];

        dp[0] = nums[0];
        for (int i = 1; i < nums_size; ++i) {
            dp[i] = nums[i];
            if (dp[i - 1] > 0) {
                dp[i] += dp[i - 1];
            }
            ans = max(ans, dp[i]);
        }
        return ans;
    }
};

3. 1706. 球会落何处

    思路:
        一道模拟题,用dfs搜索每个球的轨迹,如果能到达底部则记录位置,否则记为-1
        不能到达的条件如下
        (1)(idx == 0 && grid[row][idx] == -1),球到左边界,且向左下滚
        (2)(idx == n - 1 && grid[row][idx] == 1),球到右边界且向右下滚
        (3)(idx < n - 1 && grid[row][idx] == 1 && grid[row][idx + 1] == -1),球从左边滚到 V 中
        (4) || (idx > 0 && grid[row][idx] == -1 && grid[row][idx - 1] == 1)球从边滚到了 V 中

class Solution {
    vector<int> ans;

    void dfs(int row, int idx, vector<vector<int>> &grid, int m, int n) {

        if (row == m) {
            ans.push_back(idx);
            return ;
        }

        if ((idx == 0 && grid[row][idx] == -1) || (idx == n - 1 && grid[row][idx] == 1) || (idx < n - 1 && grid[row][idx] == 1 && grid[row][idx + 1] == -1) || (idx > 0 && grid[row][idx] == -1 && grid[row][idx - 1] == 1)) {
            ans.push_back(-1);
            return ;
        }

        if (grid[row][idx] == 1) dfs(row + 1, idx + 1, grid, m, n);
        else if (grid[row][idx] == -1) dfs(row + 1, idx - 1, grid, m, n);
    }
public:
    vector<int> findBall(vector<vector<int>>& grid) {
        int m = grid.size();
        int n = grid[0].size();
        ans.clear();
        for (int i = 0; i < n; ++i) {
            dfs(0, i, grid, m, n);
        }
        return ans;
    }
};

4. 1420. 生成数组

    思路:
        题目要求满足条件的情况是:共n个元素,每个元素的最大值是m,单调递增的元素个数不少于k个,
        利用单调栈的思想,dp[n][m][k],第一维是当前元素的个数,第二维是当前递增的最大元素,第三维是单调栈中的元素个数
        详见传送门

class Solution {
    #define mod 1000000007
    #define maxn 55
    #define maxm 105
    #define maxk 55
public:
    int numOfArrays(int n, int m, int k) {
        int dp[maxn][maxm][maxk];
        int ans = 0;
        memset(dp, 0, sizeof(dp));
        for (int j = 1; j <= m; ++j) dp[1][j][1] = 1;

        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= m; ++j) {
                for (int t = 1; t <= k; ++t) {

                    for (int jj = 1; jj <= j; ++jj) {
                        dp[i + 1][j][t] += dp[i][j][t];
                        if (dp[i + 1][j][t] >= mod) {
                            dp[i + 1][j][t] -= mod;
                        }
                    }

                    for (int jj = j + 1; jj <= m; ++jj) {
                        dp[i + 1][jj][t + 1] += dp[i][j][t];
                        if (dp[i + 1][jj][t + 1] >= mod) {
                            dp[i + 1][jj][t + 1] -= mod;
                        }
                    }
                }
            }
        }
        for (int j = 1; j <= m; ++j) {
            ans += dp[n][j][k];
            if (ans >= mod) ans -= mod;
        }
        return ans;
    }
};

posted @ 2022-06-03 14:32  番茄元  阅读(25)  评论(0)    收藏  举报