P1133 教主的花园

题目描述

教主有着一个环形的花园,他想在花园周围均匀地种上 n 棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值。

教主最喜欢 3 种树,这 3 种树的高度分别为 10,20,30。教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高。

输入格式

第一行为一个正整数 n,表示需要种的树的棵树。

接下来 n 行,每行 3 个不超过 10000 的正整数 ai​,bi​,ci​,按顺时针顺序表示了第 i 个位置种高度为 10,20,30 的树能获得的观赏价值。

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

输出格式

一个正整数,为最大的观赏价值和。

输入输出样例

输入 #1复制

4 
1 3 2 
3 1 2 
3 1 2 
3 1 2

输出 #1复制

11

说明/提示

【样例说明】。

第 1 至 n 个位置分别种上高度为 20,10,30,10 的树,价值最高。

【数据规模与约定】。

  • 对于 20% 的数据,有 n≤10;
  • 对于 40% 的数据,有 n≤100;
  • 对于 60% 的数据,有 n≤1000;
  • 对于 100% 的数据,有 4≤n≤105,并保证 n 一定为偶数。

显然的简单线性dp啊。。要那么多维干嘛?一个dp[i][1..4]就轻松过掉

首先我们需要明确目前的状态。。题目要求简谐运动一上一下。状态一共就两种(上&下):

10 -> 20/30; 20 -> 30; 30 -> 10/20; 20 -> 10;

这里我们是不是察觉到了些许的不对劲?没错!就是10 20 10 & 30 20 30 这两种情况是固定的。。所以我们对于1...n枚举4种情况就ok了

但是这样10行代码过不掉只能解决一条链。。题目要求环,而且这个环是会对相邻的元素产生贡献,所以我们需要预处理一下起始位置4种情况。最后记录答案也需要处理。然后我们就完美的过掉了这个题

//好久没写过代码和题解了。。debuged 1 hour

#include<bits/stdc++.h>
using namespace std;
const int N = 100000+5;
const int inf = 1e9;
int n, ans;
int dp[N][5]; // 1: 10 20/30; 2: 10 20 10; 3: 30 20 30; 4: 30 10/20; 
int v[N][4]; // 1: 10; 2: 20; 3: 30;
int main()
{
    cin>>n;
    for(int i = 1; i <= n; i++)
        scanf("%d%d%d", &v[i][1], &v[i][2], &v[i][3]);
    for(int j = 1; j <= 4; j++) {
        memset(dp, 0, sizeof dp);
        for(int i = 1; i <= 4; i++)
            dp[1][i] = -inf;
        if(j == 1) dp[1][j] = v[1][1];
        if(j == 2) dp[1][j] = v[1][2];
        if(j == 3) dp[1][j] = v[1][2];
        if(j == 4) dp[1][j] = v[1][3];
        for(int i = 2; i <= n; i++) {
            dp[i][1] = max(dp[i-1][2], dp[i-1][4]) + v[i][1];
            dp[i][2] = dp[i-1][1] + v[i][2];
            dp[i][3] = dp[i-1][4] + v[i][2];
            dp[i][4] = max(dp[i-1][1], dp[i-1][3]) + v[i][3];
        }
        if(j == 1) ans = max(dp[n][2], max(ans, dp[n][4]));
        if(j == 2) ans = max(ans, dp[n][1]);
        if(j == 3) ans = max(ans, dp[n][4]);
        if(j == 4) ans = max(dp[n][1], max(ans, dp[n][3]));
    }
    cout<<ans<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芙宁娜的狗是我

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值