uva 11724 Evaluate the Expression

B

Evaluate the Expression

Input: Standard Input

Output: Standard Output

 

In this problem, we will consider a mathematical expression according to the following BNF grammar:

<expression> = <variable> | <expression><operator><expression>| “(“<expression>“)”
<operator> = “+” | “*”
<variable> = “a” | “b” | “c” | … | “y” | “z”

 

When evaluating such expressions, you have to follow the conventional rules. That means you have to do things in the brackets first and multiplications have to be done before addition.

Example:  2*(3+4*2) = 22

Given an expression and some inequalities, you have to assign each variable with a positive integer so that the value of the expression is minimized.

 

Consider an example:
Expression = a+b*c and Inequalities = a>b,  c>b

 

Assignment of: a=2, b=1 and c=2 will give us the minimum value. => 2 + 1*2 = 4

 

Input

 

The first line of input is an integer T(T<100) that gives us the number of test cases. Each case starts with a line that gives you the expression. The length of the expression is at most 300. The next line contains an integer I(I<400) that gives you the number of inequalities. Each of the next Ilines will give you an inequality of the format x>y where x and y are lowercase alphabets that are present in the given expression and x is not equal to y. All the inequalities will be distinct.

 

Output

For each case, output the case number first. Then output the minimum value of the expression that can be obtained by assigning positive integers to each variable that abides by the given inequalities. You can assume the output will fit in 32 bit signed integer. If the inequalities are inconsistent, then output -1 instead.

 

Sample Input              Output for Sample Input

3
a+b*c
2
a>b
c>b
z*(x+y)
3
z>x
x>y
z>y
a+b+c+a
0

 

Case 1: 4

Case 2: 9

Case 3: 4

 


Problem Setter: Sohel Hafiz, Special Thanks: Renat Mullakhanov


题目大意:T组测试数据,对于每组测试数据,一个表达式,包含 a 到 z 的变量,以及 + 和 * 运算符,以及 左括号,右括号, 接下俩是 m 组限制条件,求出表达式的结果,要求最小。

解题思路:(1)可以先计算各个变量的值(2)根据表达式求结果。

(1)具体算法:

尽量让每个变量尽可能小,最终(2)的答案就最小,也就是所谓的贪心。

计算变量的值用的是松弛技术,对每个变量初始化赋值为1,接下来 如果 要求 a<b ,但是 实际 a>=b,那么令 a=b+1,这样赋值,反之亦然,一直松弛下去 ,

直到满足条件为止。不满足条件也就是可能存在负环,也就是 a>b,b>a,这就是负环,判断负环的方法就是松弛到一定程度还不能解决,也就是 某个变量的值大于26了

(2)具体算法:

利用编译原理这门课的思想,但是注意优化

这个表达式可以看成为 项,项又有以下三种形式:

一、 项 = (项)

二、项 =  项 +  项 

三、项 =  项 *  项

对于 项 = (项) 很简单,对于第二种和第三种,只需枚举加号或乘号的位置,划分子问题,看是否满足条件即可,记得用记忆化dp,否则超时。


解题代码:

#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
using namespace std;

string st;
vector <string> v;
int a[30],m,dp[310][310];

void input(){
    v.clear();
    for(int i=1;i<=26;i++) a[i]=1;
    cin>>st>>m;
    for(int i=0;i<m;i++){
        string tmp;
        cin>>tmp;
        v.push_back(tmp);
    }
    for(int i=0;i<=st.length();i++)
    for(int j=0;j<=st.length();j++)
        dp[i][j]=-2;
}

int isX(int l,int r){
    if(dp[l][r]!=-2) return dp[l][r];
    if(l==r) return a[st[l]-'a'+1];
    if(st[l]=='(' && st[r]==')' ) return dp[l][r]=isX(l+1,r-1);
    else{
        for(int i=l;i<=r;i++){
            if(st[i]=='+'){
                int x1=isX(l,i-1);
                if(x1<0) continue;
                int x2=isX(i+1,r);
                if(x2<0) continue;
                dp[l][i-1]=x1;dp[i+1][r]=x2;
                return dp[l][r]=x1+x2;
            }
        }
        for(int i=l;i<=r;i++){
            if(st[i]=='*'){
                int x1=isX(l,i-1);
                if(x1<0) continue;
                int x2=isX(i+1,r);
                if(x2<0) continue;
                dp[l][i-1]=x1;dp[i+1][r]=x2;
                return dp[l][r]=x1*x2;
            }
        }
        return dp[l][r]=-1;
    }
}

void computing(){
    bool flag=true;
    while(flag){
        flag=false;
        for(int i=0;i<m;i++){
            int x1=v[i][0]-'a'+1,x2=v[i][2]-'a'+1;
            if(v[i][1]=='<'){
                if( a[x1] >= a[x2] ){
                    a[x2]=a[x1]+1;
                    flag=true;
                }
                if( a[x2] > 26){
                    cout<<"-1"<<endl;
                    return;
                }
            }else{
                if( a[x1] <= a[x2] ){
                    a[x1]=a[x2]+1;
                    flag=true;
                }
                if( a[x1] > 26){
                    cout<<"-1"<<endl;
                    return;
                }
            }
        }
    }
    cout<<isX(0,st.length()-1)<<endl;
}

int main(){
    int t;
    cin>>t;
    for(int i=1;i<=t;i++){
        input();
        cout<<"Case "<<i<<": ";
        computing();
    }
    return 0;
}


 




转载于:https://www.cnblogs.com/toyking/p/3797343.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值