圆环独立集(一)
内存限制: 256 Mb时间限制: 1000 ms
题目描述
给定一个长度为 n 的环状数列 a1,a2,⋯,an,请从这些数字中间挑选出一个独立集,使得独立集中的数字之和达到最大。
所谓环状,是指在考虑相邻关系时,需要把 a1 和 an 也看做是一对邻居。所谓独立集,就是挑选出的数字在原来的圆环上不能相邻。
输入格式
第一行:单个整数表示 n。
第二行:n 个整数表示 a1,a2,⋯,an。
输出格式
单个整数:表示独立的数字之和的最大值。
数据范围
- 对于 30% 的数据,1≤n≤20;
- 对于 60% 的数据,1≤n≤5000;
- 对于 100% 的数据,1≤n≤500,000,
- 1≤ai≤1,000,000。
样例数据
输入:
5
1 1 1 1 1
输出:
2
输入:
6
100 1 1 100 1 1
输出:
200
说明:
这个例子告诉我们最优独立集不一定是最大独立集
解析:
动态规划
详见代码:
#include <bits/stdc++.h>
using namespace std;
int n;
int a[500005];
long long dp[500005][2];//取第一个点
long long dp2[500005][2];//不取第一个点
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
if (n==1) {
cout<<a[1];
return 0;
}
dp[1][0]=0;
dp[1][1]=a[1];
for(int i=2;i<=n;i++){
dp[i][0]=max(dp[i-1][0],dp[i-1][1]);//不取第i个点
dp[i][1]=dp[i-1][0]+a[i];//取第i个点
}
dp2[1][0]=0;
dp2[1][1]=0;
for(int i=2;i<=n;i++){
dp2[i][0]=max(dp2[i-1][0],dp2[i-1][1]);//不取第i个点
dp2[i][1]=dp2[i-1][0]+a[i];//取第i个点
}
cout<<max(dp[n][0],dp2[n][1]);
return 0;
}