• codevs1154能量项链 环形区间DP 细节


    中文题。。题意略

    我们知道每次枚举最后合并哪两个。。

    于是枚举中间节点k

    我犯的错误是将转移方程写成了,dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]+a[l]*a[k+1]*a[k+2])

    然而我们知道,dp[l][k]的头和尾是(l,k+1),dp[k+1][r]的头和尾是(k+1,r+1)

    我居然没分析出这一点。。困惑于如果[1,4]分成的一个子区间[2,3],dp[2][3]=dp[2][2]+dp[3][3]+a[2]*a[3]*?

    这里看成最后一次合并。。你是a[2]*a[3]*a[2]呢,还是a[2]*a[3]*a[3]*a[3+1]=(由题意)a[2]*a[3]*a[3+1],如果我们按照题意头尾分析

    我在纠结把2,3看成递归地最后一次合并应该怎么看待,如果按我的理解一开始按位置来最后俩合并的是2,3那么这俩相邻。。所以一定是互相乘

    但是实际上根本不存在2,3最后一次合并。。

    那么问题就变成了最后剩下两个就一定该互相乘吗?按照题意来说不是的

    比如说1,2,3,4,5,1,2,3,4,5

    如果按照整个区间来算比如 (3,4,5) (1,2)则这个算法总是有效

    但是

    (2,3,4)

    (2,2) (3,4)

    显然在小区间。。我们任何时候都应该考虑往右扩展,此时a[2]*a[3]*a[2]是不对的。。因为(3,4)这一部分合并完后缀一定是5

    那么会不会有一种情况导致5这个珠子已经没了呢。。不会的。。因为我们在划分的时候,你看一下上面的序列就明白

    要么1,5被隔开。。要么按5,1的顺序连在一起。。合并完前缀不还是5..所以这种情况后缀一定存在。。不必担心。。

    所以给我们的启示是。。按照题目的规则合并。。因为我们在小子区间的臆想不符合题意。。要按照头尾标号进行合并计算

    然后处理环形我们都开大一倍空间。。然后我们取i,i+(n-1)区间中最大的情况就好了,

    但是N<=100,我才开了105,多开一倍空间的话就是201!奇葩OJ给我报了WA而不是RE,真是NB。。以后一定要小心环忘记开大数组而WA

    然而后来我注意到一个显然的事实。。在小区间里发生的一定不是整个区间的最后一次合并。。并且合并计算的条件不是递归的。。而是整体静态的

    贴18ms的代码。。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    
    using namespace std;
    
    int n;
    int a[255];
    int dp[255][255];
    int dfs(int l,int r,int dep){
        // printf("DFS (%d,%d) DEP%d
    ",l,r,dep);
        if(dp[l][r]!=-1) return dp[l][r];
        if(l>=r) return dp[l][r]=0;
        int k,p=0;
        for(k=l;k<r;++k){
            p=max(p,a[l]*a[k+1]*a[r+1]+dfs(l,k,dep+1)+dfs(k+1,r,dep+1));//合并到r,则r的右端是r+1,而不是k+2
        }
        p=max(p,a[l]*a[r]*a[r+1]+dfs(l,r-1,dep+1));
        // printf("DFS (%d,%d) DEP%d ANS%d
    ",l,r,dep,p);
        return dp[l][r]=p;
    }
    
    int main(){
        scanf("%d",&n);
        int i;
        for(i=1;i<=n;++i){
            scanf("%d",a+i);
        }
        for(i=n+1;i<=2*n;++i){
            a[i]=a[i-n];
        }
        int ans=0;
        memset(dp,-1,sizeof(dp));
        dfs(1,2*n-1,0);
        for(i=1;i<=n;++i){
            ans=max(ans,dp[i][i+n-1]);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    转: CEF嵌入到单文档mfc
    浅谈C++多态性
    C++面试整理1
    面试汇总
    【转】一些经典的笔试题
    C# 委托
    搭建Nuget
    thinkphp框架之模型(数据库查询)
    利用csc.exe 手动编译C#程序
    css
  • 原文地址:https://www.cnblogs.com/linkzijun/p/6414583.html
Copyright © 2020-2023  润新知