题目描述
教主有着一个环形的花园,他想在花园周围均匀地种上n棵树,但是教主花园的土壤很特别,每个位置适合种的树都不一样,一些树可能会因为不适合这个位置的土壤而损失观赏价值。
教主最喜欢33种树,这3种树的高度分别为10,20,3010,20,30。教主希望这一圈树种得有层次感,所以任何一个位置的树要比它相邻的两棵树的高度都高或者都低,并且在此条件下,教主想要你设计出一套方案,使得观赏价值之和最高。
输入输出格式
输入格式:
第一行为一个正整数nn,表示需要种的树的棵树。
接下来nn行,每行33个不超过1000010000的正整数a_i,b_i,c_iai,bi,ci,按顺时针顺序表示了第ii个位置种高度为10,20,3010,20,30的树能获得的观赏价值。
第ii个位置的树与第i+1i+1个位置的树相邻,特别地,第11个位置的树与第nn个位置的树相邻。
输出格式:
一个正整数,为最大的观赏价值和。
输入输出样例
说明
【样例说明】
第11至nn个位置分别种上高度为20,10,30,1020,10,30,10的树,价值最高。
【数据规模与约定】
对于20\%20%的数据,有n≤10n≤10;
对于40\%40%的数据,有n≤100n≤100;
对于60\%60%的数据,有n≤1000n≤1000;
对于100\%100%的数据,有4≤n≤1000004≤n≤100000,并保证nn一定为偶数。
挺好的一道dp
一开始开了三维的 dp[i][j][k] 表示 前i个 最后一个为k 前一个为j 的最大价值 然后向后递推
只有70分 因为首尾不一定满足
然后再开一维记录首的高度即可
最后再判断一下 最后一个数是否满足 (因为知道倒数第二个和第一个)
但是还不知道首是否满足条件
题目还给了一个关键条件 n为偶数 这样一来 n-1个点满足了条件 剩下一个也必然满足条件
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f const int N=100000+5; ll dp[N][3][3][3]; int n; struct node { int v[4]; }ss[N]; int main() { RI(n); rep(i,1,n) RIII(ss[i].v[1],ss[i].v[2],ss[i].v[3]); ss[n+1]=ss[1]; rep(i,1,3) rep(j,1,3) if(i!=j) dp[2][i] [i][j]=ss[1].v[i]+ss[2].v[j]; rep(i,3,n+1) { rep(fi,1,3) rep(j,1,3)//当前 rep(s,1,3)//前一位 rep(k,1,3)//再前一位 { if(j>s&&k>s||j<s&&k<s) dp[i][fi][s][j]=max(dp[i][fi][s][j],dp[i-1][fi][k][s]+ss[i].v[j]); } } ll ans=0; rep(i,1,3) rep(j,1,3) rep(k,1,3) if( i<k&&j<k||i>k&&j>k ) ans=max(ans,dp[n][i][j][k] ); cout<<ans; return 0; }