P1133 教主的花园

链接

https://www.luogu.com.cn/problem/P1133

思路

动态规划,我开始想的差不多,首先想到使用dp[i][j]表示前i个树,在第i号位种下了j树的最大收益。这里得考虑到都比两边高/低,所以想到加一个二维1/0。
递推:dp[i][j][0] = dp[i-1][k][1] + val[i][j]
这样。然后递推k就行。关键一个点就是由于dp会忘记第一棵树是多少,所以使用for遍历第一棵树。并且做好标记(这里初始化不要用for,见代码)

代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long
const int N = 1e5 + 10;
int n;
int val[N][4];
int dp[N][4][2];

void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= 3; j++)
			cin >> val[i][j];
	int ans = 0;
	for (int ix = 1; ix <= 3; ix++)
	{
		int begin = ix;
		memset(dp, 0, sizeof(dp));
		dp[1][ix][0] = dp[1][ix][1] = val[1][ix];//初始化只用把对应的ix初始化就行了
		for (int i = 2; i <= n; i++)
		{
			dp[i][1][0] = max(dp[i - 1][2][1], dp[i - 1][3][1]) + val[i][1];
			dp[i][2][0] = dp[i - 1][3][1] + val[i][2];
			dp[i][2][1] = dp[i - 1][1][0] + val[i][2];
			dp[i][3][1] = max(dp[i - 1][1][0], dp[i - 1][2][0]) + val[i][3];
		}
		if (begin == 1)
		{
			ans = max(ans, max(dp[n][2][1], dp[n][3][1]));
		}
		else if (begin == 2)
			ans = max(ans, max(dp[n][1][0], dp[n][3][1]));
		else ans = max(ans, max(dp[n][1][0], dp[n][2][0]));
	}
	cout << ans;
}


signed main()
{
	IOS;
	solve();
	return 0;
}

posted @ 2025-03-17 16:55  WHUStar  阅读(9)  评论(0)    收藏  举报