第九届河南省ACM题解

A、表达式求值

题目简述:给你一个表达式,包括+、*以及()和Smax。让你求最后值。

一个字符串处理题,可以模拟栈来操作。每当读进一个(,则记录下位置及(个数,每读进一个)时,可以先求出这个括号内的值,(的位置用数组记录下来了,最后出现的就是。 并且为了同Smax的()区别开,可以定义不同值区分。处理完括号之后剩下+、*。扫一遍就好了。

#include<iostream>
#include<cstring>
using namespace std;
int Smax(int n, int m)
{
    int i, j;
    i = j = 0;
    while(n!=0)
    {
        i = i + n%10;
        n/=10;
    }
    while(m!=0)
    {
        j = j+m%10;
        m/=10;
    }
    return i>j?i:j;
}
int oo(int i, int j, int b[])   //判断i-j内的结果,这里面只有加号和乘 
{
    int k = 0, x, y;
    x = i;
    y = j;
    for(i; i < j; i++)
    {
        if(b[i+1] == -5)
        {
            b[i+2] = b[i]*b[i+2];
            b[i] = -1;
        i++;
        }
    }
    for(i = x; i <= j; i++)
    {
        if(b[i] >= 0)
        k+=b[i];
    }
    return k;
}
int main()
{
    char a[1001];
    int n, i, j, k, l, m, b[1001], t, c[1001][2],x,y,z;//用-1代表Smax,-2代表普通的(,-3代表),-5代表*,-9代表, 
    cin >> t;
    while(t--)
    {
    k = 0;
    cin >> a;
    n = strlen(a);
    m = 0; 
    for(i = 0; i < n; i++)
    {
        if(a[i] == '(')
        {
            m++;
            b[m] = -2;
                k++;
            c[k][0] = -2;
            c[k][1] = m;
        }
        else if(a[i] == ')')
        {
            m++;
            b[m] = -3;
            if(c[k][0] == -2)
            {
                j = c[k][1];
                b[j] = oo(j+1, m-1, b);
                m = j;
                k--;
            }
            else
            {
                j = c[k][1];
                for(z = j; z <= m; z++)
                if(b[z] == -9)
                break;
                x = oo(j+1, z-1, b);
                y = oo(z+1, m-1, b);
                b[j] = Smax(x, y);
                m = j;
            k--;
            }   
        }
        else if(a[i] == '+')
        {
            m++;
            b[m] = -4;
        }
        else if(a[i] == '*')
        {
            m++;
            b[m] = -5;
        }
        else if(a[i] == 'S')
        {
            m++;
            for(i; i < n; i++)
            if(a[i]=='(')
            break;
                k++;
            c[k][0] = -1;
            c[k][1] = m;
            b[m] = -1;
        }
        else if(a[i] == ',')
        {
            m++;
            b[m] = -9;
        }
        else
        {
            m++;
            l = 0;
            for(i ; i < n; i++)
            if(a[i]<'0' || a[i]>'9')
            break;
            else
            l = l*10+a[i]-'0';
            b[m] = l;
            i--;
        }
    }
    cout << oo(1, m, b) << endl;
    }
}

B、宣传墙

B题可以通过找公式来做出来。已知宽是4。我们可以推出大致有四种
一、第一行两个横着放,余下的就是 f(n-1)种情况。
如图
二、前两行全是竖着放,余下就是f(n-2)种情况。
无
三、两边放竖着,中间放横着,那么中间空的两个放一个横的就有f(n-2)种情况,也可以接着放竖着,再放横着。就有f(n-4)情况,总共f(n-2)+f(n-4)…
这里写图片描述
四,一边放横着,一边放竖着。于是可以选择空的地方放一个横的,就有f(n-2)种情况,也可以放两个竖的再放横的,有f(n-3)种情况。总共f(n-2)+f(n-3)…注意求出来结果*2.因为对称是一样的。
这里写图片描述

C

省赛简单题,找一条1到n的路径乘积最小。直接优先队列BFS就好了。不要直接数组。。。犹记得比赛被队友骗了直接10000*10000数组跑。233333

D

生于忧患_死于安乐
首先感谢下这位博主,这题做法也是源于这里。
http://my.csdn.net/WR_technology
题目链接导弹发射
题意一定要读懂!!! 前进就是x,y严格增加。点重合也只算一个。
还有!!! 你的两个点之间斜率也要在雷达两条线之间。
首先把雷达外的点移除去。
之后建立以两条雷达线为X,Y轴。
然后按照x或y进行从小到大排序,相同则对另一个值从大到小排。
然后就是nlogn的最长严格上升子序列。(用一个a[i]表示长度为i时最小值为多少)

E

也是一个简单题。。求最路径长度。注意double存就好了。比赛没过,代码int改double直接过233333. 最短路,bfs都可以做。

F

省赛签到题,直接枚举所有可能情况就好了。

G

简述:让你建立N个二叉搜索树,看有多少种形状不同的。
于是可以简单模拟下建立过程。每个数的位置用a[i][j]记录。 首先与第一个数比较,大于等于找a[i][j]*2+1, 小于则找有没有a[i][j]*2,找到了改变j值再次寻找。最后找不到就可以确定这个数的位置。
模拟建立代码如下

cin >> n >> k;
        for(i = 1; i <= n; i++)
        {
            cin >> b[1];
            a[i][1] = 1;
            for(j = 2; j <= k; j++)
            {
                cin >> b[j];
                y = 1;
                x = b[1];
                while(1)
                {
                if(b[j] >= x)
                {
                    for(l = 2; l < j; l++)
                    if(a[i][l] == y*2+1)
                    {
                        x = b[l];
                        y = y*2+1;
                        break;
                    }
                }
                else
                {
                    for(l = 2; l < j; l++)
                    if(a[i][l] == y*2)
                    {
                        x = b[l];
                        y = y*2;
                        break;
                    }
                }
                    if(l == j)
                    {
                        if(b[j] >= x)
                        a[i][j] = y*2+1;
                        else
                        a[i][j] = y*2;
                        break;
                    }
                }
            }
        }

H

除了暴力并不会DP。。。。。。

第一篇博客。。格式、内容等方面确实不太合理,有什么不满的地方请见谅。以后会更加努力的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值