题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3310
题解:
一道比较水的dp,一开始没有想到用两次dp来解决成环的这个问题。
具体看代码。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define met(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f
const int maxn = 1e6+10;
int dp[maxn][2];
int num[maxn];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%d",&num[i]);
met(dp,0);
dp[1][1]=num[1];
// 拿第一个物品
for(int i=2;i<=n;i++)
{
dp[i][0]= max(dp[i-1][1],dp[i-1][0]);
// dp[i][0]表示这个位置不拿,所以他的转移可以这么理解:上一个状态已经拿过了,或者上一个状态还是没有拿。
dp[i][1]=dp[i-1][0]+num[i];
// dp[i][1]表示这个状态是拿的,所以,他的上一个状态一定是不拿的。
}
int Max=dp[n][0];
met(dp,0);
// 表示第一个位置的时候没有拿物品
for(int i=2;i<=n;i++)
{
dp[i][0]=max(dp[i-1][1],dp[i-1][0]);
dp[i][1]=dp[i-1][0]+num[i];
// 这里的状态跟上面一样。
}
// 这里一共用了两次dp,一次是拿了第一个,一个是不拿第一个的,这样,就将可以将环的情况给省略掉了。
Max=max(Max,max(dp[n][0],dp[n][1]));
printf("%d\n",Max);
}
}