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\n",ans );
}

 

 

posted @ 2018-08-21 12:02  holy-unicorn  阅读(216)  评论(0编辑  收藏  举报