codeforces 39A C*++ Calculations(贪心)

该博客讨论了如何在C*++语言中计算带有变量a的数学表达式,其中a++和++a的顺序影响结果。博主提出,为了获得最大值,应当根据系数大小来决定a的计算顺序,而与a本身初始值无关。博主通过举例说明了如何按照系数从小到大的顺序计算,以确保结果最大化,并指出这种策略适用于所有此类表达式。

C*++ language is quite similar to C++. The similarity manifests itself in the fact that the programs written in C*++ sometimes behave unpredictably and lead to absolutely unexpected effects. For example, let’s imagine an arithmetic expression in C*++ that looks like this (expression is the main term):

expression ::= summand | expression + summand | expression - summand
summand ::= increment | coefficientincrement
increment ::= a++ | ++a
coefficient ::= 0|1|2|…|1000
For example, "5
a+±3*++a+a++" is a valid expression in C*++.

Thus, we have a sum consisting of several summands divided by signs “+” or “-”. Every summand is an expression “a++” or “++a” multiplied by some integer coefficient. If the coefficient is omitted, it is suggested being equal to 1.

The calculation of such sum in C*++ goes the following way. First all the summands are calculated one after another, then they are summed by the usual arithmetic rules. If the summand contains “a++”, then during the calculation first the value of the “a” variable is multiplied by the coefficient, then value of “a” is increased by 1. If the summand contains “++a”, then the actions on it are performed in the reverse order: first “a” is increased by 1, then — multiplied by the coefficient.

The summands may be calculated in any order, that’s why sometimes the result of the calculation is completely unpredictable! Your task is to find its largest possible value.

Input
The first input line contains an integer a ( - 1000 ≤ a ≤ 1000) — the initial value of the variable “a”. The next line contains an expression in C*++ language of the described type. The number of the summands in the expression does not exceed 1000. It is guaranteed that the line describing the expression contains no spaces and tabulation.

Output
Output a single number — the maximal possible value of the expression.
题意:表达式求解,和正常的运算不同的是可以选择每个被加数的运算顺序,询问最大的值是多少。

一开始想的是区间dp,枚举每个区间内最后一个被选择的a是哪个,思路应该没有问题,但是数据范围太大,区间dp搞一搞要超时,所以就放弃了dp的思路。

其实只要考虑4个式子就好,k*++a+ma++,k++a+m*++a,ka+++ma++,ka+++m++a,先算第一个再算第二个,先算第二个再算第一个,最后发现选择a计算的顺序和a的值并没有关系,只和系数有关,想让值最大,应该是按照从系数从小到大的顺序选择,在纸上一算就就能得出这个结论了。两个a顺序的顺序确定,那么n个数字的顺序也就确定了,按照系数从小到大的顺序计算能够得出正确答案。

以k*++a+ma++举个例子,先计算第一个a再算第二个,sum=k(a+1)+m*(a+1),先计算第二个再算第一个,sum=k(a+2)+m*a,两式相减得m-k,可知想让第一种选法值更大,m需要大于k,即选择更小的系数,并且顺序和a无关。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
#define maxn 1010
struct node
{
    int co;//系数
    int key;//判断是a++还是++a
} num[maxn];
int seven;//判读有无负号
char str[maxn*100];
int init;
bool cmp(node x,node y)
{
    return x.co<y.co;
}
int main()
{
    scanf("%d",&init);
    scanf("%s",str);
    seven=1;
    int cnt=1;
    int length=strlen(str);
    int now=0;
    int pre=-1;//上一个a可以达到的范围
    for(int i=1; i<=1000; i++)
        num[i].co=1;//初始化系数为1
    while(now<length)
    {
        if(str[now]=='-')
        {
            seven=-1;
            now++;
        }
        else if(str[now]=='*'||str[now]=='+')
            now++;
        else if(str[now]=='a')
        {
            if(now-2>pre&&str[now-1]=='+'&&str[now-2]=='+')//说明为++a
            {
                pre=now;//那么这一项能覆盖的位最多到现在的a,下面的pre同理
                num[cnt].co*=seven;
                num[cnt].key=0;
                cnt++;
                now++;
            }
            else
            {
                pre=now+2;
                num[cnt].co*=seven;
                num[cnt].key=1;
                cnt++;
                now+=3;
            }
            seven=1;
        }
        else
        {
            int sum=0;
            while(str[now]>='0'&&str[now]<='9')
            {
                sum=sum*10+(str[now]-'0');
                now++;
            }
            num[cnt].co=sum;
        }
    }
    cnt--;
    sort(num+1,num+1+cnt,cmp);
    int ans=0;
    for(int i=1; i<=cnt; i++)
    {
        if(!num[i].key)
        {
            init++;
            ans+=(num[i].co*init);
        }
        else
        {
            ans+=(num[i].co*init);
            init++;
        }
    }
    printf("%d\n",ans);
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值