dp6 连续子数组最大和
注意此题子数组长度最小为1.因此负数的情况也需要考虑。
由于此题我已做过多遍,不再赘述。
#include <bits/stdc++.h>
using namespace std;
int main () {
int n;
scanf("%d", &n);
int tmp = 0, sum = -101, c;
for(int i = 0; i < n; ++i) {
scanf("%d", &c);
tmp += c;
if(sum < tmp) {
sum = tmp;
}
if(tmp < 0) {
tmp = 0;
}
}
printf("%d", sum);
return 0;
}
dp7 连续子数组的最大乘积
此题基本是套着最大和的模板 关键点在于什么情况下该重置tmp
#include <bits/stdc++.h>
using namespace std;
int main () {
int n;
scanf("%d", &n);
vector<int> dp(n);
int tmp = 1, sum = -101, l = -1, r = n, c = 0;//统计最左边的负数下标 最右边负数下标 总负数个数
for(int i = 0; i < n; ++i) {
scanf("%d", &dp[i]);
if(dp[i] < 0) {
c++;
if(l == -1) {
l = i;
}
r = i;
}
}
//从头到尾
for(int i = 0; i < n; ++i) {
tmp *= dp[i];
if(sum < tmp) {//小于就更新
sum = tmp;
}
if(dp[i] == 0) {//乘0会导致后续都是0 所以需要重置tmp
tmp = 1;
}
if(i == r && (c & 1)) {//如果到了最右边 说明再也不会出现负数 同时负数个数又是奇数个数 说明当前tmp只能为负数了 这种情况下 就需要重置tmp
tmp = 1;
}
}
tmp = 1;//从尾到头
//比如 2 -2 -5 -4 3 这种情况 最优的其实是从右向左得到的-5 -4 3
for(int i = n - 1; i >= 0; --i) {
tmp *= dp[i];
if(sum < tmp) {
sum = tmp;
}
if(dp[i] == 0) {
tmp = 1;
}
if(i == l && (c & 1)) {
tmp = 1;
}
}
printf("%d", sum);
return 0;
}
dp8 乘积为正数的最大子数组长度
/*
0 负数个数为奇数
记录从负数起点到当前点前一个的长度
否则
记录tmp中的长度
重置ne, tmp, positive
正数 长度tmp增加
负数个数为奇数
记录从负数起点到当前点前一个的长度
否则
正数长度记录positive增加
记录tmp的长度
负数 当前负数个数为偶数 tmp长度增加, positive更新为tmp 记录
当前负数个数为奇数
如果后续无负数 记录长度 重置ne, tmp, positive
否则 长度增加
写到头晕
稍微总结一下
需要去记录一下最右边负数的下标 用于去判断当前乘法序列的长度是否还能增加
需要ne 用于判断当前序列的负数个数是奇数还是偶数
positive 记录当前序列乘积为正数序列的长度
tmp 记录当前序列的长度
对于
1 2 -3 4 序列
ne = 1
positive = 2
tmp = 4
如果之后遇到0了
那么应该让 tmp - positive - 1 (即[4])去更新最后的结果 (因为[1 2]在正数那里已经算过了)
然后重置各个元素
如果碰到了正数 tmp增加 记录tmp - positive - 1
如果碰到了负数
那么整个序列乘积为正 tmp++, positive = tmp 长度增加 正数序列长度置为 序列长度
*/
#include <bits/stdc++.h>
using namespace std;
int main () {
int n;
scanf("%d", &n);
vector<int> dp(n);
int tmp = 0, r = n, count = 0, ne = 0, positive = 0;//统计最左边的负数下标 最右边负数下标 总负数个数
for(int i = 0; i < n; ++i) {
scanf("%d", &dp[i]);
if(dp[i] < 0) {
r = i;
}
}
for(int i = 0; i < n; ++i) {
if(dp[i] == 0) {
if(ne & 1) {
count = max(count, tmp-1-positive);
} else {
count = max(count, tmp);
}
tmp = 0;//重置
ne = 0;
positive = 0;
} else if (dp[i] < 0) {
++ne;
if(ne & 1) { //当前负数个数为奇数
if(i < r) {//后续还有负数
++tmp;//增加长度
} else {//后续没有负数
//cout << count << ' ' << tmp << endl;
count = max(count, tmp);//记录长度
ne = 0;//重置
tmp = 0;
positive = 0;
}
} else {//偶数个数
++tmp;
positive = tmp;
count = max(count, tmp);//记录长度
}
} else {
++tmp;
if(ne & 1) {
count = max(count, tmp-1-positive);
} else {
++positive;
count = max(count, tmp);
}
}
}
printf("%d", count);
return 0;
}