《算法竞赛从入门到进阶》心得及相关题解007--dfs--hdu3350


题目意思:hdu3350,给定一个表达式,表达式只含数字、+和MAX(a,b)的表达式,其中MAX(a,b)表达式可能有嵌套,问表达式的计算结果和加法的次数。
解题思路:用结构体保存计算结果sum和加法的次数cnt,递归该表达式: 1.若第一个字母为数字,则求出该数字;若第一个字母为M,则分割成两部分,递归求出两部分的结构体u1和u2,如前半部分计算结果大于后半部分,则计算结构体u.sum=u1.sum且u.cnt=u1.cnt*2+u2.cnt,否则u.sum=u2.sum且u.cnt=u1.cnt+u2.cnt*2; 2.如该表达式后面还有+,则递归求出该表达式的结构体nu,计算u.sum+=nu.sum以及u.cnt+=nu.cnt+1。 3.返回计算结果
易错的点:MAX(a,b),如a>b才计算a表达式的加法乘以2,并非a>=b计算a表达式的加法乘以2。
代码明细:
//probID: hdu3350
//author: WiselyQY
//date: 2020-12-29
#include <bits/stdc++.h>
using namespace std;

//结构体:sum为计算结果,cnt为加法的累计数
struct Node
{
    int sum, cnt;
};
string str;
Node dfs(int s, int e)
{
    Node u;
    u.sum=u.cnt=0;
    //如果为数字则算出该数字
    if(str[s]>='0' && str[s]<='9')
    {
        while(str[s]>='0' && str[s]<='9')
        {
            u.sum=u.sum*10+str[s]-'0';
            s++;
        }
    }
    //如果为MAX格式,则分割成两部分计算
    else //if(str[i]=='M')
    {        
        s+=4;//去掉MAX(
        int left=1, j=s, k;
        while(1)
        {
            if(str[j]==')' && left==1) break; //找到MAX结束的位置
            if(str[j]==',' && left==1) k=j; //找到分割成两部分的位置
            if(str[j]=='(') left++;
            if(str[j]==')') left--;
            j++;
        }
        Node u1=dfs(s,k); //计算MAX的前半部分
        Node u2=dfs(k+1,j); //计算MAX的后半部分
        if(u1.sum>u2.sum) {u.sum=u1.sum; u.cnt=u1.cnt*2+u2.cnt;} //如果前半部分大于后半部分则前半部分的cnt乘以2计算
        else {u.sum=u2.sum; u.cnt=u1.cnt+u2.cnt*2;} //如果后半部分大于等于前半部分则后半部分的cnt乘以2计算
        s=j+1;
    }
    //后面是否还有表达式,如果有则继续计算
    if(str[s]=='+')
    {
        Node nu=dfs(s+1,e);
        u.sum+=nu.sum;
        u.cnt+=nu.cnt+1;           
    }
    return u;
}
int main()
{
    clock_t start,end;
    start=clock();
#ifndef ONLINE_JUDGE
    freopen(R"(D:\hdu\3350\in.txt)","r",stdin);
#endif
    int T;
    cin>>T;
    while(T--)
    {
        cin>>str;
        Node u=dfs(0, str.size());
        cout<<u.sum<<" "<<u.cnt<<endl;
    }
    end=clock();
    //printf("time=%lfs\n",(double)(end-start)/1000);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值