2487 小b和环
小b有一个长度为n的环,每个点上有个数字。
现在请你选出一些点,满足选出的任意两个点在环上不相邻,且选出的点的数字之和最大,
你只需输出这个最大值。
收起
输入
第一行输入一个数n,其中0<n≤50000; 第二行输入n个非负整数,第i个数表示环上顺时针第i个点上的数字,以空格隔开。 0<=每个点上的数字<=10000。输出
输出一个数,表示最大值。输入样例
4 1 2 3 1输出样例
4
思路:
最近做了不少这种一不小心就2^N的dp,这题算是最简单的一个,
状态十分简单,就是取和不取,完全没有后效性。
难点在于环形的处理,题解提供思路跑两边dp,对于第一个取还是不取
做强制规定,并初始化对应边界。
代码实现:
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<math.h>
#include<set>
#include<algorithm>
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=2e5+100;
const int M=4e5+100;
int arr[N],dp[N][2];
int main() {
int n,ans;
while(cin>>n){
ans=0;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
cin>>arr[i];
}
//
dp[1][1]=arr[1];
dp[2][1]=0;dp[2][0]=dp[1][1];
for(int i=3;i<=n;i++){
dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
dp[i][1]=dp[i-1][0]+arr[i];
}
ans=max(dp[n][0],ans);
memset(dp,0,sizeof(dp));
dp[1][1]=0;
dp[1][0]=0;
dp[2][0]=0;
dp[2][1]=arr[2];
for(int i=3;i<=n;i++){
dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
dp[i][1]=dp[i-1][0]+arr[i];
}
ans=max(ans,dp[n][1]);
ans=max(ans,dp[n][0]);
cout<<ans<<endl;
}
return 0;
}
THE END;