- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
题目描述
小明每周上班都会拿到自己的工作清单,工作清单内包含n项工作,每项工作都有对应的耗时时长(单位h)和报酬,工作的总报酬为所有已完成工作的报酬之和。那么请你帮小明安排一下工作,保证小明在指定的工作时间内工作收入最大化。
输入描述
输入的第一行为两个正整数工 T,n。T 代表工作时长(单位h,0
接下来是n行,每行包含两个整数t,w。t代表该项工作消耗的时长(单位h,t>0),w代表该项工作的报酬。
输出描述
输出小明指定工作时长内工作可获得的最大报酬。
#include
#include
#include
using namespace std;
int main() {
int T, n;
cin >> T >> n;
vector<vector<int>> dp(T + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= n; ++i) {
int t, w;
cin >> t >> w;
for (int j = T; j >= t; --j) {
dp[j][i] = max(dp[j][i-1], dp[j-t][i-1] + w);
}
}
cout << dp[T][n] << endl;
return 0;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
3.最长公共子序列(Longest Common Subsequence, LCS)
最长公共子序列(Longest Common Subsequence, LCS)问题是计算机科学中的一个经典问题,它要求找出两个序列(通常是字符串)的最长公共子序列,且要求子序列中的元素在原序列中是连续的。
问题描述
给定两个序列 X 和 Y,求它们的最长公共子序列的长度。
#include
#include
#include
using namespace std;
int lcs(const string& X, const string& Y) {
int m = X.length();
int n = Y.length();
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (X[i - 1] == Y[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}
int main() {
string X = "ABCBDAB";
string Y = "BDCABC";
cout << "最长公共子序列的长度为: " << lcs(X, Y) << endl;
return 0;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
4.最长递增子序列(Longest Increasing Subsequence, LIS)
问题描述:给定一个整数序列 a1, a2, …, an,求其最长递增子序列的长度。
动态规划解法:使用一维数组存储到当前位置为止的最长递增子序列长度。
#include
#include
using namespace std;
int lis(const vector<int>& a) {
int n = a.size();
vector<int> dp(n, 1);
for (int i = 1; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (a[i] > a[j]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
int maxLength = 0;
for (int i = 0; i < n; ++i) {
maxLength = max(maxLength, dp[i]);
}
return maxLength;
}
int main() {
vector<int> a = {10, 9, 2, 5, 3, 7, 101, 18};
cout << "最长递增子序列的长度为: " << lis(a) << endl;
return 0;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
5.矩阵链乘问题(Matrix Chain Multiplication)
问题描述:给定一系列的矩阵,求将它们相乘的最小计算量。
动态规划解法:使用三维数组存储不同矩阵组合的最小乘法次数。
#include
#include
#include
using namespace std;
int matrixChainMultiplication(const vector<int>& p) {
int n = p.size() - 1;
vector<vector<int>> dp(n + 1, vector<int>(n + 1, 0));
for (int len = 2; len <= n; ++len) {
for (int i = 1; i <= n - len + 1; ++i) {
int j = i + len - 1;
dp[i][j] = INT_MAX;
for (int k = i; k < j; ++k) {
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + p[i - 1] * p[k] * p[j]);
}
}
}
return dp[1][n];
}
int main() {
vector<int> p = {30, 35, 15, 5, 10, 20, 25};
cout << "最小乘法运算次数为: " << matrixChainMultiplication(p) << endl;
return 0;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
6.编辑距离(Edit Distance)
问题描述:给定两个字符串 str1 和 str2,求将 str1 转换为 str2 的最小编辑距离。
动态规划解法:使用二维数组存储两个字符串之间的编辑距离。
#include
#include
#include
#include
using namespace std;
int editDistance(const string& str1, const string& str2) {
int m = str1.length();
int n = str2.length();
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for (int i = 0; i <= m; ++i) {
dp[i][0] = i;
}
for (int j = 0; j <= n; ++j) {
dp[0][j] = j;
}
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (str1[i - 1] == str2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = 1 + min({dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]});
}
}
}
return dp[m][n];
}
int main() {
string str1 = "sunday";
string str2 = "saturday";
cout << "最小编辑距离为: " << editDistance(str1, str2) << endl;
return 0;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
7.硬币找零问题(Coin Change Problem)
问题描述:给定不同面额的硬币和总金额,计算组成总金额的最少硬币数量。
动态规划解法:使用一维数组存储达到每个金额所需的最少硬币数量。
#include
#include
#include
using namespace std;
int coinChange(const vector<int>& coins, int amount) {
vector<int> dp(amount + 1, INT_MAX);
dp[0] = 0;
for (int i = 1; i <= amount; ++i) {
for (int j = 0; j < coins.size(); ++j) {
if (i - coins[j] >= 0 && dp[i - coins[j]] != INT_MAX) {
dp[i] = min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] == INT_MAX ? -1 : dp[amount];
}
int main() {
vector<int> coins = {1, 2, 5};
int amount = 11;
cout << "最少硬币数量为: " << coinChange(coins, amount) << endl;
return 0;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
8.最小路径和(Minimum Path Sum)
问题描述:在一个二维矩阵中,从左上角到右下角,只能向右或向下移动,求路径的最小和。
动态规划解法:使用二维数组存储到达每个点的最小路径和。
#include
#include
using namespace std;
int minPathSum(const vector<vector<int>>& matrix) {
int m = matrix.size();
int n = matrix[0].size();
vector<vector<int>> dp(m, vector<int>(n, 0));
dp[0][0] = matrix[0][0];
for (int i = 1; i < m; ++i) {
dp[i][0] = dp[i - 1][0] + matrix[i][0];
}
for (int j = 1; j < n; ++j) {
dp[0][j] = dp[0][j - 1] + matrix[0][j];
}
for (int i = 1; i < m; ++i) {
for (int j = 1; j < n; ++j) {
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + matrix[i][j];
}
}
return dp[m - 1][n - 1];
}
int main() {
vector<vector<int>> matrix
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
9.股票买卖问题(Stock Buy and Sell)
问题描述:给定股票价格序列,确定买卖股票的最佳时机以获得最大利润。
动态规划解法:使用一维数组存储每个时间点的最大利润。
#include
#include
using namespace std;
int maxProfit(const vector<int>& prices) {
int n = prices.size();
if (n <= 1) return 0;
vector<int> dp(n, 0);
for (int i = 1; i < n; ++i) {
if (prices[i] > prices[i - 1]) {
dp[i] = dp[i - 1] + (prices[i] - prices[i - 1]);
} else {
dp[i] = dp[i - 1];
}
}
return dp[n - 1];
}
int main() {
vector<int> prices = {7, 1, 5, 3, 6, 4};
cout << "最大利润为: " << maxProfit(prices) << endl;
return 0;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
10.三步问题

class Solution {
public:
int waysToStep(int n) {
long long dp[1000000]={0};
dp[1]=1;
dp[2]=2;
dp[3]=4;
for(int i=4;i<=n;i++)
{
dp[i]=(dp[i-1]+dp[i-2]+dp[i-3])%1000000007;
}
return dp[n];
}
};
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
11.连续数列

class Solution {
public:
int maxSubArray(vector<int>& nums) {
int dp[100000]={0};
int ans=nums[0];
dp[0]=nums[0];
for(int i=1;i<nums.size();i++)
{
dp[i]=max(nums[i],dp[i-1]+nums[i]);
ans=max(dp[i],ans);
}
return ans;
}
};
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
12.不同路径

class Solution {
public:
int uniquePaths(int m, int n) {
int dp[m][n];
if(m==0||n==0)
return 0;
for(int i=0;i<n;i++)
{
dp[0][i]=1;
}
for(int i=0;i<m;i++)
{
dp[i][0]=1;
}
for(int i=1;i<m;i++)
{
for(int j=1;j<n;j++)
{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
};
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
13.最小路径和

这题和上题很类似,转移方程也十分的相似,因为只能向右或者向下走,所以我们只要考虑向下和向右走哪个能符合题目条件即可,我们可以将上题的转移方程变式一下,就可以得到:
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];
class Solution {
public:
int minPathSum(vector<vector<int>>& grid) {
int dp[grid.size()][grid[0].size()];
dp[0][0]=grid[0][0];
for(int i=1;i<grid.size();i++)
dp[i][0]=dp[i-1][0]+grid[i][0];
for(int i=1;i<grid[0].size();i++)
dp[0][i]=dp[0][i-1]+grid[0][i];
for(int i=1;i<grid.size();i++)
{
for(int j=1;j<grid[0].size();j++)
{
dp[i][j]=min(dp[i-1][j],dp[i][j-1])+grid[i][j];
}
}
return dp[grid.size()-1][grid[0].size()-1];
}
};
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/weixin_43988686/article/details/144438103","extend1":"pc","ab":"new"}">>
评论记录:
回复评论: