提问人:noroong 提问时间:11/9/2023 最后编辑:Remy Lebeaunoroong 更新时间:11/9/2023 访问量:81
如何找到最大乘积的总和?
How to find the sum of the maximum product?
问:
当给定 n 个整数时,您可以将两个数字相乘或保持原样。我编写了一个算法来找到所有值加在一起的最大值。
例如,输入为:
9(数组长度) -1 -8 2 1 3 6 -5 0 1
输出需要为 62:
62=-8x-5+0x-1+6x3+2+1+1
如果数组是 ,则答案应为 91。如果数组是 ,则答案应为 838。7 4 1 2 5 3 1 9 0
-13 7 -12 13 -8 4 12 7 15 6 -2 10 9 15 4 1 -15
我是这样编写代码的:
#include <iostream>
#include "sop.h"
using namespace std;
sop::sop() {
this->num = 0;
this->array = NULL;
}
sop::sop(int* a, int n) {
this->num = n;
this->array = new int[n];
for (int i = 0; i < n; i++) this->array[i] = a[i];
}
sop::~sop() {
if (this->array) {
delete[] this->array;
}
this->num = 0;
this->array = NULL;
}
void sop::printArray(void) {
if (!this->num) return;
for (int i = 0; i < num; i++) cout << array[i] << " ";
cout << endl;
}
int myMax(int a, int b) {
return (a > b) ? a : b;
}
int sop::maxSOP() {
if (num == 0) return 0;
if (num == 1) return array[0];
int maxSum = array[0]; // Initialize maxSum to the first element
int currentMax = array[0]; // Initialize currentMax to the first element
for (int i = 1; i < num; i++) {
int temp = currentMax; // Store the previous currentMax
// Calculate the current maximum product including the current element
currentMax = myMax(array[i], myMax(currentMax * array[i], temp * array[i]));
// Update maxSum with the maximum of maxSum and currentMax
maxSum = myMax(maxSum, currentMax);
}
return maxSum;
}
maxSOP
这就是我所做的。myMax
在此代码中,结果是 288,而不是 62。我不知道为什么。你能修复这个代码吗?我将向您展示可以帮助您修复此代码的其他文件。
其他文件.cpp
#include <iostream>
#include <fstream>
#include "sop.h"
using namespace std;
int main(int argc, char* argv[]) {
int i = 0;
int num = 0;
int* array = NULL;
ifstream fin;
sop* _sop = NULL;
if (argc > 1) {
fin.open(argv[1]);
if (!fin.is_open()) {
cerr << "File " << argv[1] << " does not exist!" << endl;
exit(0);
}
fin >> num;
array = new int[num];
for (i = 0;i < num;i++) fin >> array[i];
fin.close();
}
else {
cin >> num;
array = new int[num];
for (i = 0;i < num;i++) cin >> array[i];
}
_sop = new sop(array, num);
cout << "Input array: ";
_sop->printArray();
cout << "Maximum sum of products = " << _sop->maxSOP() << endl;
delete _sop;
if (array) delete[] array;
array = NULL;
return 0;
}
otherheader.h
#include <iostream>
#include <fstream>
#include "sop.h"
using namespace std;
int main(int argc, char* argv[]) {
int i = 0;
int num = 0;
int* array = NULL;
ifstream fin;
sop* _sop = NULL;
if (argc > 1) {
fin.open(argv[1]);
if (!fin.is_open()) {
cerr << "File " << argv[1] << " does not exist!" << endl;
exit(0);
}
fin >> num;
array = new int[num];
for (i = 0;i < num;i++) fin >> array[i];
fin.close();
}
else {
cin >> num;
array = new int[num];
for (i = 0;i < num;i++) cin >> array[i];
}
_sop = new sop(array, num);
cout << "Input array: ";
_sop->printArray();
cout << "Maximum sum of products = " << _sop->maxSOP() << endl;
delete _sop;
if (array) delete[] array;
array = NULL;
return 0;
}
答:
3赞
Atmo
11/9/2023
#1
基本上,如果您能够有效地将数字配对在一起,您将获得最高的总和。我建议以下规则:
- 数字 <= 0 应该配对在一起。
对于 和 , .
与配对相反:这不是我们想要的配对。n1 <= 0
n2 <= 0
n1 * n2 >= n1 + n2
n1 <= 0
n2 > 0
n1 * n2 < n1 + n2
1
永远不应该配对。
同上:如果我们与 1 配对,则结果乘积将始终小于 。n
n+1
- 数字 > 1 应该配对在一起。
不管你选择什么,(只有当两边相等时;在其他情况下,这是一个严格的不等式)。n1 > 1
n2 > 1
n1 * n2 >= n1 + n2
n1 = n2 = 2
- 当您有超过 2 个可以配对的数字时(如上述 3 条规则所述),请务必先选择更高的绝对值。
3 个整数的示例:
。
类似的东西也适用于 4 个整数 :您可以构建的最大组合是 。1 < n1 <= n2 <= n3
n2 * n3 + n1 >= n1 * n3 + n2 >= n1 * n1 + n3 >= n1 + n2 + n3
1 < n1 <= n2 <= n3 <= n4
n1 * n2 + n3 * n4
这几乎使我们走上了正轨;我们必须:
- 对数字进行排序(因为规则 4)
- 将列表分为 3 个部分(因为规则 1、2、3)。在每一步中,我们首先成对处理项目(即将迭代器增加 2),然后如果该段的元素数量为奇数,我们将最小的(绝对值)剩余项目添加到总和中。
该算法看起来有点不对称,因为 预计 位于向量的中间,因此我们将在负数循环之后处理它们(而不是从 重新启动)。1
numbers.begin()
#include <algorithm>
#include <vector>
int main(int argc, char* argv[])
{
//std::vector<int> numbers{ -1, -8, 2, 1, 3, 6, -5, 0, 1 };
//std::vector<int> numbers{ 7, 4, 1, 2, 5, 3, 1, 9, 0 };
std::vector<int> numbers{ -13, 7, -12, 13, -8, 4, 12, 7, 15, 6, -2, 10, 9, 15, 4, 1, -15 };
int sum = 0;
std::sort(numbers.begin(), numbers.end());
{
//Start with numbers <= 0
auto iter1 = numbers.begin(), iter2 = iter1 + 1;
for (; iter2 != numbers.end() && *iter2 <= 0; iter2 += 2) {
sum += *iter1 * *iter2;
iter1 += 2;
if (iter1 == numbers.end())
break;
}
//Process the 1's
for (;iter1 != numbers.end() && *iter1 <= 1; ++iter1)
sum += *iter1;
}
{
//Process numbers > 0 (using a reverse iterator)
auto iter1 = numbers.rbegin(), iter2 = iter1 + 1;
for (; iter2 != numbers.rend() && *iter2 > 1; iter2 += 2) {
sum += *iter1 * *iter2;
iter1 += 2;
if (iter1 == numbers.rend())
break;
}
if (iter1 != numbers.rend() && *iter1 > 1)
sum += *iter1;
}
std::cout << sum << std::endl;
return 0;
}
我允许您添加回所有要将用户输入推送到的行。numbers
如果您想知道,复杂性是因为初始排序。O(n log(n))
评论
0赞
Toby Speight
11/9/2023
这很好地演示了原理,但需要一些工作才能完成它,因为当我们的数字都是正数或全负数时,可以是 UB。OP 应该添加一套很好的测试来清除剩余的错误。iter2 += 2
0赞
Atmo
11/9/2023
这是一个很好的观点,我花了比我预期的更长的时间来写我的答案,我想我有点太匆忙了。现在它已更正 + 在我使用它时添加了小细节。
评论