洛谷 题解 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;
}
posted @ 2019-05-06 13:06  hulean  阅读(214)  评论(0编辑  收藏  举报