题目链接:

  ZOJ 1958. Friends

  题目简介:

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

  (2)用运算符三种集合运算,'+' 表示两个集合的并集,'*' 表示两个集合的交集, '-' 表示从第一个集合中排除第二个集合包含的元素。

  (3)给出这样的表达式,求出表达式结果(按照字母顺序)。运算符优先级和编程语言中的规定相同,即优先级从高到低为括号,乘号,加/减号;相同优先级时从左向右。

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

  题目分析:

  属于常规的表达式求值,方法是借助两个栈来解析。本质上来讲,这是一个简单题目,但是细节比较繁琐,要写对需要耐心。集合可以用 bitset 来表示这个集合,由于集合的元素数目不会超过 26,因此用 uint32 整数即可表示集合,这样可以把集合运算转换为整数的位操作来完成,比直接处理字符串更加方便。例如:

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

  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[];
unsigned int stack_num[];
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 : return ;
case '(': return bInStack? : ;
case ')': return ;
case '+': return ;
case '-': return ;
case '*': return ;
}
return ;
} /*
{ABCDEFG}+
| |
str ret_val
*/
char* GetNumber(char *str, unsigned int *pNum)
{
char *pCh = str + ;
*pNum = ; while(*pCh != '}')
{
if(*pCh >= 'A' && *pCh <= 'Z')
*pNum = *pNum | ( << (*pCh - 'A')); ++pCh;
}
return pCh;
} unsigned int Compute(char* line)
{
char *pCh;
unsigned int n1, n2, result;
int prec1, prec2; top_op = ;
stack_op[top_op] = '('; top_num = -;
pCh = line; while()
{
if(*pCh == '{')
{
pCh = GetNumber(pCh, &n1);
++top_num;
stack_num[top_num] = n1;
}
else
{
prec2 = GetPrecedence(*pCh, );
prec1 = GetPrecedence(stack_op[top_op], );
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 - ];
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], );
} if(*pCh == ')')
{
while(stack_op[top_op] != '(')
{
--top_op;
}
--top_op;
}
else if(*pCh == )
break;
else
{
/* push current operator into stack */
++top_op;
stack_op[top_op] = *pCh;
}
}
}
++pCh;
} /* __ENDOF__ while(1) */ if(top_num == )
result = stack_num[];
else
result = ;
return result;
} int main(int argc, char* argv[])
{
unsigned int result, x;
char line[]; while(gets(line) != NULL)
{
result = Compute(line);
printf("{");
for(x = ; x < ; x++)
{
if(result & ( << x))
printf("%c", x + 'A');
}
printf("}\n");
}
return ;
}

zoj_1958_code

  提交结果:

Judge Status Problem ID Language Run Time(ms) Run Memory(KB)
Accepted 1958 C 0 172

ZOJ 1958. Friends的更多相关文章

  1. ZOJ题目分类

    ZOJ题目分类初学者题: 1001 1037 1048 1049 1051 1067 1115 1151 1201 1205 1216 1240 1241 1242 1251 1292 1331 13 ...

  2. ZOJ People Counting

    第十三届浙江省大学生程序设计竞赛 I 题, 一道模拟题. ZOJ  3944http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=394 ...

  3. ZOJ 3686 A Simple Tree Problem

    A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a rooted tree, each no ...

  4. ZOJ Problem Set - 1394 Polar Explorer

    这道题目还是简单的,但是自己WA了好几次,总结下: 1.对输入的总结,加上上次ZOJ Problem Set - 1334 Basically Speaking ac代码及总结这道题目的总结 题目要求 ...

  5. ZOJ Problem Set - 1392 The Hardest Problem Ever

    放了一个长长的暑假,可能是这辈子最后一个这么长的暑假了吧,呵呵...今天来实验室了,先找了zoj上面简单的题目练练手直接贴代码了,不解释,就是一道简单的密文转换问题: #include <std ...

  6. ZOJ Problem Set - 1049 I Think I Need a Houseboat

    这道题目说白了是一道平面几何的数学问题,重在理解题目的意思: 题目说,弗雷德想买地盖房养老,但是土地每年会被密西西比河淹掉一部分,而且经调查是以半圆形的方式淹没的,每年淹没50平方英里,以初始水岸线为 ...

  7. ZOJ Problem Set - 1006 Do the Untwist

    今天在ZOJ上做了道很简单的题目是关于加密解密问题的,此题的关键点就在于求余的逆运算: 比如假设都是正整数 A=(B-C)%D 则 B - C = D*n + A 其中 A < D 移项 B = ...

  8. ZOJ Problem Set - 1001 A + B Problem

    ZOJ ACM题集,编译环境VC6.0 #include <stdio.h> int main() { int a,b; while(scanf("%d%d",& ...

  9. zoj 1788 Quad Trees

    zoj 1788 先输入初始化MAP ,然后要根据MAP 建立一个四分树,自下而上建立,先建立完整的一棵树,然后根据四个相邻的格 值相同则进行合并,(这又是递归的伟大),逐次向上递归 四分树建立完后, ...

随机推荐

  1. 在Android Studio中使用lambda表达式

    build.gradle中添加以下配置 Android{ ..... compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targ ...

  2. 请求网络get

    package com.baidu.net; import java.io.IOException; import org.apache.http.HttpEntity;import org.apac ...

  3. NLP概述

    1,词法分析 待续 2,文本分类 文本表示: 重点是贝叶斯模型:二项表示法和多项表示法.(向量维度为词库大小,一个是01,一个是频次).模型重点在于化后验为先验. 还有其他模型:机器学习模型,分布式模 ...

  4. Codeforces Round #169 (Div. 2)

    A. Lunch Rush 模拟. B. Little Girl and Game 因为可以打乱顺序,所以只关心每种数字打奇偶性. 若一开始就是回文,即奇数字母为0或1种,则先手获胜. 若奇数字母大于 ...

  5. Eclipse动态web工程(Dynamic Web Project)添加jar文件的正确方法

    Eclipse中,创建了动态web工程之后,如果需要添加新的jar文件,有两种方法.第一种是配置工程的“build path”,第二种则是将jar文件放在工程目录下的“/WebContent/WEB- ...

  6. c# 映射对比测试

    c#  映射对比测试(测试对象,测试案例,测试结果) 测试组件对象: TinyMapper-EmitMapper-AutoMapper-NLiteMapper-Handwritten 对比测试案例: ...

  7. quick sort 的简化实现

    Pivot 随机选取意义不大 第一种方法使用随机pivot,使得尽可能平均二分序列,而实际上一般来说需要排序的集合往往是乱序的,无需重新生成随机数作为pivot,大可使用固定位置的数作为pivot,这 ...

  8. 第一次在linux上登录博客

    这是我第一次在linux操作系统上登录博客,额,虽然是在X-window上面.好吧,是我太激动了. 这意味着我已经步入linux的世界了,虽然中文输入法不太好用,但是我还是写一下我的心情吧. 从去年的 ...

  9. How to create/restore a slave using GTID replication in MySQL 5.6

    MySQL 5.6 is GA! Now we have new things to play with and in my personal opinion the most interesting ...

  10. Asp.net MVC 的八个扩展点

    http://www.cnblogs.com/richieyang/p/5180939.html MVC模型以低耦合.可重用.可维护性高等众多优点已逐渐代替了WebForm模型.能够灵活使用MVC提供 ...