【发布时间】:2021-03-26 23:38:21
【问题描述】:
我被这个问题困住了。
给定一个数字数组。在每一步,我们都可以在这个数组中选择一个像 N 这样的数字,并将 N 与这个数组中存在的另一个数字相加。我们继续这个过程,直到这个数组中的所有数字都为零。最少需要多少步? (我们可以保证最初这个数组中的数字之和为零)。
示例:-20,-15,1,3,7,9,15
- 第 1 步:选择 -15 并与 15 相加 -> -20,0,1,3,7,9,0
- 第 2 步:选择 9 并与 -20 相加 -> -11,0,1,3,7,0,0
- 第 3 步:选择 7 并与 -11 相加 -> -4,0,1,3,0,0,0
- 第 4 步:选择 3 并与 -4 相加 -> -1,0,1,0,0,0,0
- 第 5 步:选择 1 并与 -1 相加 -> 0,0,0,0,0,0,0
所以这个例子的答案是 5。
我尝试过使用贪心算法。它的工作原理是这样的:
在每一步中,我们都会选择该数组中已有的最大和最小数字,并将这两个数字相加,直到该数组中的所有数字都为零。
但它不起作用并且给我错误的答案。谁能帮我解决这个问题?
#include <bits/stdc++.h>
using namespace std;
int a[] = {-20,-15,1,3,7,9,15};
int bruteforce(){
bool isEqualToZero = 1;
for (int i=0;i<(sizeof(a)/sizeof(int));i++)
if (a[i] != 0){
isEqualToZero = 0;
break;
}
if (isEqualToZero)
return 0;
int tmp=0,m=1e9;
for (int i=0;i<(sizeof(a)/sizeof(int));i++){
for (int j=i+1;j<(sizeof(a)/sizeof(int));j++){
if (a[i]*a[j] >= 0) continue;
tmp = a[j];
a[i] += a[j];
a[j] = 0;
m = min(m,bruteforce());
a[j] = tmp;
a[i] -= tmp;
}
}
return m+1;
}
int main()
{
cout << bruteforce();
}
这是我为这个问题编写的蛮力方法。有什么算法可以更快地解决这个问题吗?
【问题讨论】:
-
问题的任何来源/参考?一个网址可能会有所帮助。
-
@DeepakTatyajiAhire 实际上,我提出了这个问题。我想找到解决这个问题的最佳算法。
-
@DeepakTatyajiAhire 我在谷歌上搜索过这个问题或任何类似的问题,但我没有找到任何对我有帮助的东西。
-
这看起来像是一个 NP 完全问题。贪心算法不可能总是找到最佳解决方案。数组的最大大小是多少?
-
@Damien 实际上,这不是学校作业或竞赛问题。我正在寻找一种算法来尽快解决这个问题。