给定一个长度为n
的数组,如果不允许选择多于两个连续的数组元素,则需要找到可以选择的元素的最大总和。例如;
n=5;
arr[5] = {10,3,5,7,3};
Output : 23
10+3+7+3=23
所以我写了这段代码;
#include <stdio.h>
#include <stdlib.h>
int max=0;
void solve(int arr[],int ind,int sum,int n,int count)
{
if(ind==n){
if(sum>max)
max=sum;
}
else{
sum+=arr[ind];
if(ind==n-1)
solve(arr,ind+1,sum,n,1);
if(ind==n-2 && count>1)
solve(arr,ind+2,sum,n,1);
if(ind<n-1 && count<2){
count++;
solve(arr,ind+1,sum,n,count);
}
if(ind<n-2)
solve(arr,ind+2,sum,n,1);
if(ind<n-3)
solve(arr,ind+3,sum,n,1);
}
}
int main()
{
int n;
scanf("%d",&n);
int i=0,arr[n];
while(i<n){
scanf("%d",&arr[i]);
i++;
}
int count=1;
//going into all three possibilities
solve(arr,0,0,n,count);
solve(arr,1,0,n,count);
solve(arr,2,0,n,count);
printf("%d\n",max);
return 0;
}
此程序为n<1000
生成预期输出,但显示较大输入的运行时错误(SIGSEGV)。可能是什么原因?
更有效的解决方案也值得欢迎.....
答案 0 :(得分:3)
使用动态编程
DP [i]:来自&#34; i&#34;索引
有7个案例:
1-使用第一和第二元素
2-使用第二和第三元素
3-使用第一和第三元素
4-仅使用第一个元素
5-仅使用第二个元素
6-仅使用第三个元素
7-不使用任何元素
int F(int[] a)
{
if (a.Length == 1)
{
return Max(a[0], 0);
}
int n = a.Length;
int[] DP = new int[n];
DP[n - 1] = Max(a[n - 1], 0);
DP[n - 2] = DP[n - 1] + Max(a[n - 2], 0);
for (int i = n - 3; i >= 0; i--)
{
DP[i] = Max(a[i], 0) + Max(a[i + 1], 0) + (i + 3 < n ? DP[i + 3] : 0);// first and second
DP[i] = Max(DP[i], Max(a[i + 1], 0) + Max(a[i + 2], 0) + (i + 4 < n ? DP[i + 4] : 0));// second and third
DP[i] = Max(DP[i], Max(a[i + 0], 0) + Max(a[i + 2], 0) + (i + 4 < n ? DP[i + 4] : 0));// first and third
DP[i] = Max(DP[i], Max(a[i + 0], 0) + (i + 2 < n ? DP[i + 2] : 0));// first
DP[i] = Max(DP[i], Max(a[i + 1], 0) + (i + 3 < n ? DP[i + 3] : 0));// second
DP[i] = Max(DP[i], Max(a[i + 2], 0) + (i + 4 < n ? DP[i + 4] : 0));// third
DP[i] = Max(DP[i], DP[i + 1]);// none
}
return DP[0];
}
例1:
int[] a = new int[] { 10, 3, 5, 7, 3 };
writer.WriteLine(F(a));
输出:
23
例2:
int[] a = new int[] { 1, 5, 2, 6, 9, 8, 20, 12, 41, 3, 0, 9, 95, 6, 74, 85, 20, 14, 26, 35, 14, 72, 15 };
writer.WriteLine(F(a));
输出:
496
答案 1 :(得分:1)
这个问题有一个相当简单的动态编程解决方案。
数组中的每个项目都代表一个二元选择:它可以选择也可以不选择。但是,如果选择了两个连续项目,则无法选择下一个项目。因此,对于数组中的每个项目,我们需要跟踪三个总和
以下是代码:
#include <stdio.h>
#define max3(a) (a[0]>a[1] ? a[0]>a[2]?a[0]:a[2] : a[1]>a[2]?a[1]:a[2])
int main( void )
{
int array[] = { 10,3,7,55,60,62,4,2,5,42,8,9,12,5,1 };
int N = sizeof(array) / sizeof(array[0]);
int dp[N][3];
dp[0][0] = 0;
dp[0][1] = array[0];
dp[0][2] = 0;
for ( int i = 1; i < N; i++ )
{
dp[i][0] = max3(dp[i-1]);
dp[i][1] = dp[i-1][0] + array[i];
dp[i][2] = dp[i-1][1] + array[i];
}
printf( "%d\n", max3(dp[N-1]) );
}
此程序的输出为208
。要了解如何计算,请查看dp
数组的内容:
请注意,直到最后才知道通过dp
数组的正确路径。在此示例中,两个端点具有相同的总和,因此通过数组有两条路径可以给出相同的答案。这两条路径代表了这些选择:
array: 10 3 7 55 60 62 4 2 5 42 8 9 12 5 1
red: 10 +7 +60+62 +2 +42+8 +12+5 = 208
blue: 10 +7 +60+62 +5+42 +9+12 +1 = 208