vijos1470教主的后花园

这道题本来看见有环,以为和环有关,要拆环,后来发现根本不用,这一个的状态只和前一个有关,只会影响后一个,所以一遍推过去就好啦。。。
f[i][j][k]表示前i个,第i个种第j种树(10,20,30),k表示比前一个高(0),还是矮(1)。
这里我用了一个很笨的方法来处理第一个与第N个的关系……
就是硬性规定第一个种什么样的树,分四种情况10比n矮的,20比n高,20比n矮,30比n高,分别比较答案。
代码:
#include
#include
#include
using namespace std;
int high[110000][5],f[110000][5][2],ans,n;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&high[i][1],&high[i][2],&high[i][3]);
    memset(f,0,sizeof(f));
    f[1][1][1]=high[1][1];//算第一种情况
    for(int i=2;i<=n;i++){
        f[i][1][1]=max(f[i-1][2][0],f[i-1][3][0])+high[i][1];
        f[i][2][1]=f[i-1][3][0]+high[i][2];
        f[i][2][0]=f[i-1][1][1]+high[i][2];
        f[i][3][0]=max(f[i-1][2][1],f[i-1][1][1])+high[i][3];
    }
    ans=max(ans,max(f[n][2][0],f[n][3][0]));
    memset(f,0,sizeof(f));
    f[1][2][1]=high[1][2];//算第二种情况
    for(int i=2;i<=n;i++){
        f[i][1][1]=max(f[i-1][2][0],f[i-1][3][0])+high[i][1];
        f[i][2][1]=f[i-1][3][0]+high[i][2];
        f[i][2][0]=f[i-1][1][1]+high[i][2];
        f[i][3][0]=max(f[i-1][2][1],f[i-1][1][1])+high[i][3];
    }
    ans=max(ans,f[n][3][0]);
    memset(f,0,sizeof(f));
    f[1][2][0]=high[1][2];//算第三种情况
    for(int i=2;i<=n;i++){
        f[i][1][1]=max(f[i-1][2][0],f[i-1][3][0])+high[i][1];
        f[i][2][1]=f[i-1][3][0]+high[i][2];
        f[i][2][0]=f[i-1][1][1]+high[i][2];
        f[i][3][0]=max(f[i-1][2][1],f[i-1][1][1])+high[i][3];
    }
    ans=max(ans,f[n][1][1]);
    memset(f,0,sizeof(f));
    f[1][3][0]=high[1][3];//算第四种情况
    for(int i=2;i<=n;i++){
        f[i][1][1]=max(f[i-1][2][0],f[i-1][3][0])+high[i][1];
        f[i][2][1]=f[i-1][3][0]+high[i][2];
        f[i][2][0]=f[i-1][1][1]+high[i][2];
        f[i][3][0]=max(f[i-1][2][1],f[i-1][1][1])+high[i][3];
    }
    ans=max(ans,max(f[n][1][1],f[n][2][1]));
    printf("%d",ans);
    return 0;
}

你可能感兴趣的:(vijos题解,动态规划)