ZOJ 1958. Friends

  題目連接:編程

  ZOJ 1958. Friends編程語言

  題目簡介:ide

 

  (1)題目中的集合由 A-Z 的大寫字母組成,例如 "{ABC}" 的字符串表示 A,B,C 組成的集合。ui

  (2)用運算符三種集合運算,'+' 表示兩個集合的並集,'*' 表示兩個集合的交集, '-' 表示從第一個集合中排除第二個集合包含的元素。編碼

  (3)給出這樣的表達式,求出表達式結果(按照字母順序)。運算符優先級和編程語言中的規定相同,即優先級從高到低爲括號,乘號,加/減號;相同優先級時從左向右。spa

  例如: "{ABC}+{BCD}" = "{ABCD}";code

 

  題目分析:blog

 

  屬於常規的表達式求值,方法是藉助兩個棧來解析。本質上來說,這是一個簡單題目,可是細節比較繁瑣,要寫對須要耐心。集合能夠用 bitset 來表示這個集合,因爲集合的元素數目不會超過 26,所以用 uint32 整數便可表示集合,這樣能夠把集合運算轉換爲整數的位操做來完成,比直接處理字符串更加方便。例如:字符串

  s1: { A } -> n1 = 0x01;get

  s2: { B } -> n2 = 0x02;

 

  則:(s1+s2)轉換爲(n1 | n2)。

  

  題目聲明輸入數據都是合法的表達式,不須要考慮表達式合法性判斷。則只須要表達式的解析,解析過程由運算符驅動,其中須要注意的細節有:

 

  (1)左括號在棧內和棧外的優先級須要區分對待(在棧外具備最高優先級,入棧後則優先級下降,以讓後續的運算符可以入棧)。

  (2)右括號實際上不入棧,而是做爲一個信號,負責把和它匹配的左括號從棧中彈出。

  (3)在解析前,提早在運算符棧中壓入一個左括號,這樣編碼形式就會統一(不須要考慮在最開始階段,取不到棧內的運算符優先級的問題)。

  (4)解析結束後,取出操做數棧中的惟一元素便可。再將其解析爲字符串形式。

 

  須要考慮的特殊狀況好比:

  ({A})+({B})  至關於:(1)+(2);

 

  提交代碼:

#include <stdio.h>
#include <string.h>

char stack_op[256];
unsigned int stack_num[256];
int top_op;
int top_num;

int GetPrecedence(char op, int bInStack);
char* GetNumber(char *str, unsigned int *pNum);
unsigned int Compute(char* line);
int main(int argc, char* argv[]);

int GetPrecedence(char op, int bInStack)
{
    switch(op)
    {
    case 0: return 1;
    case '(': return bInStack? 1 : 100;
    case ')': return 1;
    case '+': return 2;
    case '-': return 2;
    case '*': return 3;
    }
    return 0;
}

/*
    {ABCDEFG}+
     |      |
    str     ret_val
*/
char* GetNumber(char *str, unsigned int *pNum)
{
    char *pCh = str + 1;
    *pNum = 0;

    while(*pCh != '}')
    {
        if(*pCh >= 'A' && *pCh <= 'Z')
            *pNum = *pNum | (1 << (*pCh - 'A'));

        ++pCh;
    }
    return pCh;
}

unsigned int Compute(char* line)
{
    char *pCh;
    unsigned int n1, n2, result;
    int prec1, prec2;

    top_op = 0;
    stack_op[top_op] = '(';

    top_num = -1;
    pCh = line;

    while(1)
    {
        if(*pCh == '{')
        {
            pCh = GetNumber(pCh, &n1);
            ++top_num;
            stack_num[top_num] = n1;
        }
        else
        {
            prec2 = GetPrecedence(*pCh, 0);
            prec1 = GetPrecedence(stack_op[top_op], 1);
            if(prec2 > prec1)
            {
                ++top_op;
                stack_op[top_op] = *pCh;
            }
            else
            {
                while(prec2 <= prec1 && strchr("*+-", stack_op[top_op]) != NULL)
                {
                    n1 = stack_num[top_num - 1];
                    n2 = stack_num[top_num];
                    switch(stack_op[top_op])
                    {
                    case '+': result = (n1 | n2); break;
                    case '-': result = (n1 & (~n2)); break;
                    case '*': result = (n1 & n2); break;
                    }
                    --top_num;
                    stack_num[top_num] = result;
                    --top_op;
                    prec1 = GetPrecedence(stack_op[top_op], 1);
                }
                
                if(*pCh == ')')
                {
                    while(stack_op[top_op] != '(')
                    {
                        --top_op;
                    }
                    --top_op;
                }
                else if(*pCh == 0)
                    break;
                else
                {
                    /* push current operator into stack */
                    ++top_op;
                    stack_op[top_op] = *pCh;
                }
            }
        }
        ++pCh;
    } /* __ENDOF__ while(1) */

    if(top_num == 0)
        result = stack_num[0];
    else
        result = 0;
    return result;
}

int main(int argc, char* argv[])
{
    unsigned int result, x;
    char line[256];

    while(gets(line) != NULL)
    {
        result = Compute(line);
        printf("{");
        for(x = 0; x < 26; x++)
        {
            if(result & (1 << x))
                printf("%c", x + 'A');
        }
        printf("}\n");
    }
    return 0;
}
zoj_1958_code

  提交結果:

Judge Status Problem ID Language Run Time(ms) Run Memory(KB)
Accepted 1958 C 0 172
相關文章
相關標籤/搜索