五月集训(第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;
}
};
东方欲晓,莫道君行早。