zoukankan      html  css  js  c++  java
  • 51Nod 1452 加括号

    题意:
    有一个算术表达式 x1 Δ x2 Δ x3 Δ ,..., Δ xn, x1,x2,x3,...,xn 是1到 9的数字, Δ是'+'或者'*'。
    现在要求你在这个表达式中加一对括号,使得这个式子的值最大。
    样例解释:3 + 5 * (7 + 8) * 4 = 303。
    题解:
    ①区间DP预处理出任意i~j之间的表达式的值

    ②贪心枚举括号的左右端点

    ③此题AC

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=5000+10;
    typedef long long LL;
    char s[maxn];
    int n,Pre[maxn],Next[maxn];
    LL f[maxn][maxn];
    void Prework();
    void Tanxin();
    signed main(){
            scanf("%s",s+1);
            n=strlen(s+1);
            Prework();
            Tanxin();
            return 0;
    }
    void Prework(){
            Pre[0]=0;
            for(int i=1;i<=n;i++)//Pre[i]记录i之前离i最近的'+'的位置
                    if(s[i]=='+')Pre[i]=i;
                    else Pre[i]=Pre[i-1];
            Next[n+1]=n+1;
            for(int i=n;i>=1;i--)//Next[i]记录i之后离i最近的'+'的位置
                    if(s[i]=='+')Next[i]=i;
                    else Next[i]=Next[i+1];
            for(int i=1;i<=n;i+=2)f[i][i]=s[i]-'0';
            for(int len=3;len<=n;len+=2)//f[i][j]表示将i~j用括号括起来,i~j的值为多少
                    for(int i=1,j;(j=i+len-1)<=n;i+=2)
                            if(Pre[j]<i)f[i][j]=f[i][j-2]*(s[j]-'0');
                            //Pre[j]<i,说明[i,j-2]和j之间是'*'
                            else f[i][j]=f[i][Pre[j]-1]+f[Pre[j]+1][j];
                            //否则说明[i,j-2]和j之间是'+'
    }
    void Tanxin(){
            LL ans=f[1][n];
            for(int i=1;i<=n;i+=2){
                    for(int j=i+2;j<=n;j+=2){
                            if(s[i-1]!='*' && s[j+1]!='*')continue;
                            //枚举()的左右边界[i,j]
                            //只有将两个'*'之间的式子扩起来才能获得更优答案
                            LL Add=0;//Add记录和[i,j]相加的值
                            if(Pre[i]>0)Add+=f[1][Pre[i]-1];
                            //只有i左边还有'+',i左边才能有不和[i,j]有关的值
                            if(Next[j]<n+1)Add+=f[Next[j]+1][n];
                            //j的右边同理
                            LL Multi=f[i][j];//Multi记录和[i,j]相乘之后的值
                            if(Pre[i]+1<=i-2)Multi*=f[Pre[i]+1][i-2];
                            //i左边第一个'*'向右到i-2的所有式子都是与[i,j]相乘
                            if(Next[j]-1>=j+2)Multi*=f[j+2][Next[j]-1];
                            //j右边同理
                            ans=max(ans,Add+Multi);
                    }
            }
            printf("%lld
    ",ans );
    }

     

  • 相关阅读:
    开发笔记-图片拉伸保持不变形
    开发笔记-简单渐变动画的实现
    开发笔记- iOS监听某些事件的方法简单梳理
    开发笔记-UIApplication代理
    开发笔记-UIApplication单例
    常见的UNIX命令
    知识点回顾-简单的TableView单组数据展示/多组数据展示
    开发技巧-改变按钮属性3部曲
    字典--plist
    如何使用JS实现页面内容随机显示
  • 原文地址:https://www.cnblogs.com/holy-unicorn/p/9510585.html
Copyright © 2011-2022 走看看