举例分析(2018年大华软件大赛赛题)
1.给定一个正数数组,找出不相邻元素的子序列的和的最大值。
如:2、5、3、9 最大的子序列是5、9,应该返回14;
8、5、3、9、1 最大的子序列是8、9,应该返回17;
5、4、10、100、10、5 最大的子序列是5、100、5,应该返回110;
输入描述:
第一行:指定用例数量T;
第二行:数组长度N;
第三行:数组元素C[i];
输出描述:
子序列的和的最大值
例如:
Input:
2
6
5 4 10 100 10 5
4
3 2 7 10
Output:
110
13
解题分析:
如果前n项不相邻元素的子序列的和的最大值为a,则前n+1项不相邻元素的子序列的和的最大值可能为前n-1项不相邻元素的子序列的和的最大值+第n项的数字,也可能还是等于如果前n项不相邻元素的子序列的和的最大值。取两者较大的就是前n+1项不相邻元素的子序列的和。
例如:
数组:5、4、10、100、10、5、9、1、2
前5项不相邻元素的子序列的和为105(最大的子序列是5、100);
前6项不相邻元素的子序列的和为110(最大的子序列是5、100、5);
第七项是9,那么前7项最大的子序列和为max(105+9,110)=114;
由此得到结论;如果知道前n-2项的最大不相邻子序列的和记做a,前n-1项的最大不相邻子序列的和记做b,第n项的数值c,则前n项的最大不相邻子序列的和为max(a+c,b)
因此可以先算出前1项和前2项的最大不相邻子序列的和,采用递归的方法计算后面的结果;
答案(c语言实现):
include <stdio.h>
void read() {
int n;
scanf("%d", &n);
int arr[n];
for (int i = 0; i < n; ++i) {
scanf("%d", arr + i);
}
if (arr[0]>arr[1]) {
arr[1] =arr[0];
}
int count1=0;
int count2=0;
for (int i = 2; i < n; ++i) {
int count1=arr[i]+arr[i-2];
int count2=arr[i-1];
if (count1>count2) {
arr[i] =count1;
}else{
arr[i] =count2;
}
}
printf("%d",arr[n-1]);
printf("\n");
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
read();
}
return 0;
}