目录
题目描述
Description
一天,主人买来N个BONE(1 <= N <= 150,000),从左向右排成一排. 狗狗想把所有的BONE全吃了,但这似乎不太可能的.主人说:狗狗,你做为我的宠物,应该要足够的聪明伶俐,睿智过人,玉树临风.我来考一下你.这里每一个BONE都有一个分数K(1<=K<=500)。你从第一个BONE开始.对于每个BONE,你可选也可不选。选择多少个也随便你但你必须从第一个开始选,从左选到右。当你选好BONE后。我会将第一个BONE的分值乘上一个1,第二个则乘上一个-1第三个又是一个1,第四个又是一个-1.然后再加起来。我希望总分值最大。你应该如何选呢?
Format
Input
第一行给出一个数字N,代表有多少块Bone. 下面N行,每行一个数字,代表每块Bone的权值。
Output
如题
Samples
输入数据 1
8 7 2 1 8 4 3 5 6
Copy
输出数据 1
17
Copy
输入数据 2
3 10 2 2
Copy
输出数据 2
10
Copy
Hint
取7 1 8 3 6,得到+7-1+8-3+6=17。
数组(贪心算法)
贪心算法做这道题,思路简单的不能再简单,就是在奇数次时,就找大的,如果下一个比它小了,就停下选这一个,偶数次则反之。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)//这是宏定义,相当于for循环,日常偷懒
using namespace std;
int bo[150000];
int main()
{
long long a,sum=0,k=1,i=1;
cin>>a;
rep(i,1,a){
cin>>bo[i];
}
while(i<=a){
if(k)
{
if(bo[i]<bo[i+1]&&i<a)i++;
else
{
sum+=bo[i];
k=0;
i++;
}
}
else
{
if(bo[i]>bo[i+1]&&i<=a)i++;
else
{
sum-=bo[i];
k=1;
i++;
}
}
}
cout<<sum;
}
线性DP
线性DP做,情况也不复杂,只有两种情况:选、不选。这里不同的是,我么需定义两个数组,一个是控制奇数次,相加情况,一个是控制偶数次,相减情况。
ji[i]=max(ji[i-1],ou[i-1]+a[i])
ou[i]=max(ou[i-1],ji[i-1]-a[i])
搞懂这俩式子,这题毫无问题。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define ll long long
using namespace std;
int ji[150001],ou[150001],ai[150001];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>ai[i];
}
for(int i=1;i<=n;i++){
ji[i]=max(ji[i-1],ou[i-1]+ai[i]);
ou[i]=max(ou[i-1],ji[i-1]-ai[i]);
}
cout<<max(ji[n],ou[n]);
return 0;
}