洛谷 题解 P1133 【教主的花园】

$n<=10^5 $

O(n)算法

  • 状态
dp[i][j][k]表示在第i个位置,种j*10的高度的树,且这棵树是否比相邻两棵树高
  • 转移
dp[i][1][0]=max(dp[i-1][2][1],dp[i-1][3][1])+a[i];
//种高度为10的树,肯定比相邻的两棵树矮
dp[i][2][0]=dp[i-1][3][1]+b[i];
//种高度为20且高度比相邻的矮的,那么第i-1棵肯定是高度为30且比相邻的两棵高的
dp[i][2][1]=dp[i-1][1][0]+b[i];
//种高度为20且高度比相邻的高的,那么第i-1棵肯定是高度为10且比相邻的两棵矮的
dp[i][3][1]=max(dp[i-1][1][0],dp[i-1][2][0])+c[i];
//种高度为30的树,肯定比相邻的两棵树高
  • 答案
取dp[n][1][0]、dp[n][2][0]、dp[n][2][1]、dp[n][3][1]的最大值

但是只有70分...

特别地,第1个位置的树与第n个位置的树相邻。

这个好像没有考虑过

所以要把位置为1的特殊处理

dp[1][1][0]=max(dp[n][2][1],dp[n][3][1])+a[1];
dp[1][2][0]=dp[n][3][1]+b[1];
dp[1][2][1]=dp[n][1][0]+b[1];
dp[1][3][1]=max(dp[n][1][0],dp[n][2][0])+c[1];

那么答案就应该是这个:

取dp[1][1][0]、dp[1][2][0]、dp[1][2][1]、dp[1][3][1]的最大值

完整代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100000+10;
int n;
int a[MAXN],b[MAXN],c[MAXN];
int dp[MAXN][4][2];
inline int read()
{
    int tot=0;
    char c=getchar();
    while(c<'0'||c>'9')
        c=getchar();
    while(c>='0'&&c<='9')
    {
        tot=tot*10+c-'0';
        c=getchar();
    }
    return tot;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read(),b[i]=read(),c[i]=read();
    for(int i=2;i<=n;i++)
    {
        dp[i][1][0]=max(dp[i-1][2][1],dp[i-1][3][1])+a[i];
        dp[i][2][0]=dp[i-1][3][1]+b[i];
        dp[i][2][1]=dp[i-1][1][0]+b[i];
        dp[i][3][1]=max(dp[i-1][1][0],dp[i-1][2][0])+c[i];
    }
    dp[1][1][0]=max(dp[n][2][1],dp[n][3][1])+a[1];
    dp[1][2][0]=dp[n][3][1]+b[1];
    dp[1][2][1]=dp[n][1][0]+b[1];
    dp[1][3][1]=max(dp[n][1][0],dp[n][2][0])+c[1];
    cout<<max(dp[1][1][0],max(dp[1][2][0],max(dp[1][2][1],dp[1][3][1])))<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hulean/p/10818987.html