• #dp#NOIP2020.9.26模拟jerry


    题目

    Jerry 写下了一个只由非负整数和加减号组成的算式。
    它想给这个算式添加合法的括号,使得算式的结果最大。


    分析

    考场(O(n^3))伪部分分成功爆零,
    (dp[i][j])表示前(i)个数中缺了(j)个右括号需要配对的最大结果,
    那就考虑是加一个括号(第(i)个数前是负号)或不变或配对一个括号,
    但是感性理解一下缺了三个或以上的右括号实际上可以被两个以内所代替
    (三重否定为否定)。由于正数是可以合并的,所以括号是可以被拆开成两部分的
    那么这道题就可以(O(n))解决了


    代码

    #include <cstdio>
    #include <cctype>
    #define rr register
    using namespace std;
    const int N=100011; typedef long long lll;
    int n,a[N],b[N]; lll dp[N][3];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline lll max(lll a,lll b){return a>b?a:b;}
    signed main(){
    	freopen("jerry.in","r",stdin);
    	freopen("jerry.out","w",stdout); 
    	for (rr int T=iut();T;--T){
    		n=iut(),b[1]=0;
    		for (rr int i=1;i<=n;++i){
    			a[i]=iut();
    			if (i==n) continue;
    			rr char c=getchar();
    			while (c!='+'&&c!='-') c=getchar();
    			b[i+1]=(c=='-');
    		}
    		dp[0][0]=0,dp[0][1]=dp[0][2]=-1e18;
    		for (rr int i=1;i<=n;++i)
    		if (b[i]){
    			dp[i][0]=-1e18;//前面是负号强行加括号,所以不可能
    			dp[i][1]=max(max(dp[i-1][0],dp[i-1][1]),dp[i-1][2])-a[i];
    			dp[i][2]=max(dp[i-1][1],dp[i-1][2])+a[i];//变号
    		}else{
    			dp[i][0]=max(max(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+a[i];
    			dp[i][1]=max(dp[i-1][1],dp[i-1][2])-a[i];//变号
    			dp[i][2]=dp[i-1][2]+a[i];//两次变号符号不变
    		}
    		printf("%lld
    ",max(max(dp[n][0],dp[n][1]),dp[n][2]));
    	}
    	return 0;
    } 
    
  • 相关阅读:
    (2).net体系
    (1)php开篇常识
    java基础知识-xx
    java基础知识-字符串与数组
    java基础知识-流程控制
    小明的喷漆计划
    加分二叉树
    括号序列
    P1045
    胖男孩
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13817190.html
Copyright © 2020-2023  润新知