题目:教主的花园
思路:
假如没有环时,令f[i][j][fa]表示对于前i棵树,位置为i的树高度为j,位置为i-1的树高度为fa的最大观赏价值(这里的高度指1,2,3 而非10,20,30)。
转移方程:f[i][j][fa]=max(f[i][j][fa],f[i-1][fa][grd]+a[i][j]) ,其中grd表示位置为i-2的树的高度,且满足grd<j<i或grd>j>i。
当有环时,处理方法是断环为链。断环为链可以将整个数组复制一遍,而这里也可以采用多加一维状态来处理这种特殊情况。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 100000
int n;
int a[maxn+5][4]={0};
int f[maxn+5][4][4][4]={0};
int dp(){
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
f[1][i][j][i]=a[1][i];
}
}
for(int i=2;i<=n;i++)
for(int j=1;j<=3;j++)
for(int fa=1;fa<=3;fa++)
for(int grd=1;grd<=3;grd++)
for(int frs=1;frs<=3;frs++){
if((j<fa&&fa>grd)||(j>fa&&fa<grd))
f[i][j][fa][frs]=max(f[i][j][fa][frs],f[i-1][fa][grd][frs]+a[i][j]);
}
int ans=0;
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
for(int k=1;k<=3;k++){
if((i<j&&j>k)||(i>j&&j<k))
ans=max(ans,f[n][j][i][k]);
}
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d%d",&a[i][1],&a[i][2],&a[i][3]);
}
int ans=dp();
printf("%d",ans);
return 0;
}