一、
1.代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int maxSubArray(vector<int>& nums) {
if (nums.empty()) return 0;
int max_current = nums[0];
int max_global = nums[0];
for (int i = 1; i < nums.size(); ++i) {
max_current = max(nums[i], max_current + nums[i]);
if (max_current > max_global) {
max_global = max_current;
}
}
return max_global;
}
int main() {
int n;
cin >> n;
vector<int> nums(n);
for (int i = 0; i < n; ++i) {
cin >> nums[i];
}
int result = maxSubArray(nums);
cout << result << endl;
return 0;
}
2.思路
-
初始化:设置两个变量,
max_current和max_global,分别用于存储当前子数组的最大和以及全局最大和。初始时,它们都可以设置为数组的第一个元素。 -
遍历数组:从数组的第二个元素开始遍历。对于每个元素,更新
max_current为当前元素本身或当前元素加上max_current中的较大值。这表示要么从当前元素开始新的子数组,要么继续扩展当前的子数组。 -
更新全局最大值:在每次更新
max_current后,如果max_current大于max_global,则更新max_global。 -
返回结果:遍历结束后,
max_global即为最大子数组的和。
二、
1.代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int T, M;
cin >> T >> M;
vector<int> time(M), value(M);
for (int i = 0; i < M; ++i) {
cin >> time[i] >> value[i];
}
vector<vector<int>> dp(M + 1, vector<int>(T + 1, 0));
for (int i = 1; i <= M; ++i) {
for (int j = 0; j <= T; ++j) {
if (j >= time[i-1]) {
dp[i][j] = max(dp[i-1][j], dp[i-1][j-time[i-1]] + value[i-1]);
} else {
dp[i][j] = dp[i-1][j];
}
}
}
cout << dp[M][T] << endl;
return 0;
}
2.思路
-
定义状态:我们使用一个二维数组
dp[i][j]来表示前i种草药在时间j内可以获得的最大价值。 -
状态转移方程:
-
如果不选择第
i种草药,那么dp[i][j] = dp[i-1][j]。 -
如果选择第
i种草药,那么dp[i][j] = dp[i-1][j-time[i]] + value[i],其中time[i]是采摘第i种草药所需的时间,value[i]是第i种草药的价值。 -
最终,
dp[i][j]取上述两种情况的最大值。
-
-
初始化:
dp[0][j] = 0,表示没有草药时,无论有多少时间,总价值都是0。 -
结果:
dp[M][T]即为在时间T内可以获得的最大价值。
三、
1.代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n, W;
cin >> n >> W;
vector<int> v, w;
for (int i = 0; i < n; ++i) {
int vi, wi, mi;
cin >> vi >> wi >> mi;
// Binary splitting
for (int k = 1; k <= mi; k *= 2) {
v.push_back(vi * k);
w.push_back(wi * k);
mi -= k;
}
if (mi > 0) {
v.push_back(vi * mi);
w.push_back(wi * mi);
}
}
vector<int> dp(W + 1, 0);
for (int i = 0; i < v.size(); ++i) {
for (int j = W; j >= w[i]; --j) {
dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
}
}
cout << dp[W] << endl;
return 0;
}
2.思路
-
定义状态:我们使用一个一维数组
dp[j]来表示在载重为j的情况下可以获得的最大价值。 -
状态转移方程:
-
对于每种宝物,我们考虑选择0到
m_i件该宝物。 -
对于每种可能的载重
j,我们更新dp[j]为选择当前宝物和不选择当前宝物中的最大值。
-
-
优化:为了减少时间复杂度,可以使用二进制拆分的方法将多重背包问题转化为0-1背包问题。具体来说,将每种宝物的数量
m_i拆分成若干个2的幂次方的和,然后将这些拆分后的宝物视为独立的0-1背包问题。
四、
1.代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> p1(n), p2(n);
for (int i = 0; i < n; ++i) {
cin >> p1[i];
}
for (int i = 0; i < n; ++i) {
cin >> p2[i];
}
// Create a position array for p2
vector<int> pos(n + 1);
for (int i = 0; i < n; ++i) {
pos[p2[i]] = i;
}
// Convert p1 to a sequence of positions in p2
vector<int> seq(n);
for (int i = 0; i < n; ++i) {
seq[i] = pos[p1[i]];
}
// Find the length of the longest increasing subsequence in seq
vector<int> dp;
for (int i = 0; i < n; ++i) {
auto it = lower_bound(dp.begin(), dp.end(), seq[i]);
if (it == dp.end()) {
dp.push_back(seq[i]);
} else {
*it = seq[i];
}
}
cout << dp.size() << endl;
return 0;
}
2.思路
-
位置映射:首先,我们为第二个排列创建一个位置数组
pos,其中pos[i]表示数字i在第二个排列中的位置。 -
转换排列:将第一个排列转换为一个新的序列
seq,其中每个元素是其在第二个排列中的位置。 -
寻找LIS:在新的序列
seq中寻找最长递增子序列(LIS),其长度即为两个排列的最长公共子序列的长度。
ACM集训代码解析与思路分享
633

被折叠的 条评论
为什么被折叠?



