日照——栈与队列

P1054 等价表达式

题目描述

明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。

这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?

这个选择题中的每个表达式都满足下面的性质:

1. 表达式只可能包含一个变量‘a’。

2. 表达式中出现的数都是正整数,而且都小于10000。

3. 表达式中可以包括四种运算‘+’(加),‘-’(减),‘*’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘*’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)

4. 幂指数只可能是1到10之间的正整数(包括1和10)。

5. 表达式内部,头部或者尾部都可能有一些多余的空格。

下面是一些合理的表达式的例子:

((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9……

输入输出格式

输入格式:

输入文件equal.in的第一行给出的是题干中的表达式。第二行是一个整数n(2 <= n <= 26),表示选项的个数。后面n行,每行包括一个选项中的表达式。这n个选项的标号分别是A,B,C,D……

输入中的表达式的长度都不超过50个字符,而且保证选项中总有表达式和题干中的表达式是等价的。

输出格式:

输出文件equal.out包括一行,这一行包括一系列选项的标号,表示哪些选项是和题干中的表达式等价的。选项的标号按照字母顺序排列,而且之间没有空格。

输入输出样例

输入样例#1:
( a + 1) ^2
3
(a-1)^2+4*a
a + 1+ a
a^2 + 2 * a * 1 + 1^2 + 10 -10 +a -a
输出样例#1:
AC

说明

对于30%的数据,表达式中只可能出现两种运算符‘+’和‘-’;

对于其它的数据,四种运算符‘+’,‘-’,‘*’,‘^’在表达式中都可能出现。

对于全部的数据,表达式中都可能出现小括号‘(’和‘)’。

2005年提高组第四题

 思路:

  关于a的表达式??这么复杂的式子判断是否相等,难道我要合并同类项?NoNoNo~

  机智的方法:给a代入特殊值。(不要代入0,1,-1这样的数,最好代质数, 只代入一个数还是很有可能出现两个不等的式子算出来结果相等, 多代几个数)

  还有一个问题,代数的话,计算结果可能会超过long long范围。 计算的时候记得模一个大质数 因为我们取了若干个数代进去,所以即使模了一个数冲突的几率也很小

  下面进入正题:如何计算表达式的值? 我们需要开两个栈:一个用来存储数字,一个用来存储符号。

   读入数字时,压入数字栈

  读入符号时:

  1.如果是运算符,当前栈顶的运算符优先级大于等于新运算符,则将栈顶运算符弹出,并将当前数字栈顶的两个数进行相应运算,弹出旧数,压入新结果。不停循环,直到栈里面没有符号或符号优先级低于当前新运算符。

  2.如果是(,直接压入栈。

  3.如果是),则依次将栈里面的符号弹出,并计算。直到遇到一个(。

  小技巧:可以在表达式开头和结尾分别加一个括号,避免了边界的特殊处理。

上代码:

#define x1 17
#define x2 29
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int inf = 7000007;
int p,n,len,topnum=0,topsym=0;
long long ansa,ansb;
char a[51],sym[51];
struct Node{
    long long y1,y2;
}num[51];

short level(char ch) {
    switch (ch) {
        case '+':
            return 1;
            break;
        case '-':
            return 1;
            break;
        case '*':
            return 2;
            break;
        case '^':
            return 3;
            break;
        case '(':
            return 0;
            break;
    }
}

void calc(char ch) {
    long long a1=num[topnum-1].y1,b1=num[topnum].y1;
    long long a2=num[topnum-1].y2,b2=num[topnum].y2;
    if(ch=='+') {
        num[topnum-1].y1=(a1+b1)%inf;
        num[--topnum].y2=(a2+b2)%inf;
    } else if(ch=='-') {
        num[topnum-1].y1=(a1-b1)%inf;
        if(num[topnum-1].y1<0) num[topnum-1].y1+=inf;
        num[--topnum].y2=(a2-b2)%inf;
        if(num[topnum].y2<0) num[topnum].y2+=inf;
    } else if(ch=='*') {
        num[topnum-1].y1=(a1%inf*b1)%inf;
        num[--topnum].y2=(a2%inf*b2)%inf;
    } else if(ch=='^') {
        long long cnt=a1;
        for(int i=1; i<b1; i++)
            cnt=(cnt*a1)%inf;
        num[topnum-1].y1=cnt;
        cnt=a2;
        for(int i=1; i<b2; i++)
            cnt=(cnt*a2)%inf;
        num[--topnum].y2=cnt;
    }
}

void work() {
    gets(a);
    len=strlen(a);
    p=0;
    while(p<len) {
        if(a[p]==' ') {
            p++;
            continue;
        }
        if(a[p]>='0' && a[p]<='9') {
            int x=a[p++]-'0';
            while(a[p]>='0' && a[p]<='9')
                x=10*x+a[p++]-'0';
            p--;
            num[++topnum].y1=x;
            num[topnum].y2=x;
        } else if(a[p]=='a') {
            num[++topnum].y1=x1;
            num[topnum].y2=x2;
        } else if(a[p]=='(') sym[++topsym]='(';
        else if(a[p]==')') {
            while(topsym>1 && sym[topsym]!='(')
                calc(sym[topsym--]);
            if(topsym>=1) topsym--;
        } else if(topsym==0 || level(sym[topsym])<level(a[p]))
            sym[++topsym]=a[p];
        else {
            calc(sym[topsym--]);
            while(topsym>0 && level(sym[topsym])>=level(a[p]))
                calc(sym[topsym--]);
            sym[++topsym]=a[p];
        }
        p++;
    }
    while(topsym>0) 
        calc(sym[topsym--]);
}

int main() {
    work();
    ansa=num[1].y1;
    ansb=num[1].y2;
    topnum=0;
    scanf("%d",&n);
    gets(a);
    for(int i=0; i<n; i++) {
        work();
        if(num[1].y1==ansa && num[1].y2==ansb)
            printf("%c",'A'+i);
        topnum=0;
    }
    return 0;
}
等价表达式

P3572 [POI2014]PTA-Little Bird

题目描述

In the Byteotian Line Forest there are  trees in a row.

On top of the first one, there is a little bird who would like to fly over to the top of the last tree.

Being in fact very little, the bird might lack the strength to fly there without any stop.

If the bird is sitting on top of the tree no. , then in a single flight leg it can fly toany of the trees no. , and then has to rest afterward.

Moreover, flying up is far harder to flying down. A flight leg is tiresome if it ends in a tree at leastas high as the one where is started. Otherwise the flight leg is not tiresome.

The goal is to select the trees on which the little bird will land so that the overall flight is leasttiresome, i.e., it has the minimum number of tiresome legs.

We note that birds are social creatures, and our bird has a few bird-friends who would also like to getfrom the first tree to the last one. The stamina of all the birds varies,so the bird's friends may have different values of the parameter .

Help all the birds, little and big!

从1开始,跳到比当前矮的不消耗体力,否则消耗一点体力,每次询问有一个步伐限制,求每次最少耗费多少体力

输入输出格式

输入格式:

There is a single integer  () in the first line of the standard input:

the number of trees in the Byteotian Line Forest.

The second line of input holds  integers  ()separated by single spaces:  is the height of the -th tree.

The third line of the input holds a single integer  (): the number of birds whoseflights need to be planned.

The following  lines describe these birds: in the -th of these lines, there is an integ…

输出格式:

Your program should print exactly  lines to the standard output.

In the -th line, it should specify the minimum number of tiresome flight legs of the -th bird.

输入输出样例

输入样例#1:
9
4 6 3 6 3 7 2 6 5
2
2
5
输出样例#1:
2
1

说明

从1开始,跳到比当前矮的不消耗体力,否则消耗一点体力,每次询问有一个步伐限制,求每次最少耗费多少体力

 思路:

注意,如果对于两个位置j1和j2,有f[j1]<f[j2],则j1一定比j2更优。因为就算j1高度比较矮,到达i顶多再多消耗1个疲劳值,顶多和j2相等。

如果不需要消耗疲劳值,比j2更优。 如果f[j1]=f[j2],则我们比较它们的高度D,高度高的更优。

上代码:

#include<cstdio>
#include<iostream>
using namespace std;

const int M = 1000001;
int n,m,h[M],dp[M],que[M],ask;

int main() {
    scanf("%d",&n);
    for(int i=1; i<=n; i++) 
        scanf("%d",&h[i]);
    scanf("%d",&m);
    while(m--) {
        scanf("%d",&ask);
        int l=0,r=0;
        que[r]=1;
        dp[1]=0;
        for(int i=2; i<=n; i++) {
            while(l<=r && (que[l]+ask<i)) l++;
            if(h[que[l]]>h[i]) dp[i]=dp[que[l]];
            else dp[i]=dp[que[l]]+1;
            while(l<=r && (dp[que[r]]>dp[i] || dp[que[r]]==dp[i]&&h[que[r]]<h[i]) ) r--;
            que[++r]=i;
        }
        printf("%d
",dp[n]);
    }
    return 0;
}
Little Bird

自己选的路,跪着也要走完!!!

原文地址:https://www.cnblogs.com/wsdestdq/p/7304981.html