CSP、T3 逻辑表达式

题目描述

在山的那边海的那边,有一群蓝精灵,他们活泼又聪明,他们……偶然有一天发现了一组神奇的逻辑表达式,这组表达式可以表示数字x处于的范围。
例如
x >= 3 && x <= 5 ||
x >= 8 && x <= 11 ||
x >= 7 ||
x <= 0
可是蓝精灵们觉得这样的表达式过于冗杂了,他们立志要不破坏x表达范围的同时将表达式简化,使这组表达式出现的与x比较的整数常量尽可能少。
蓝精灵们发现了一个秘密,x一定是[-32768,32767]内的数字。

输入

输入包含T行。
每一行有一个或两个比较表达式组成,由运算符"&&“分隔,每个比较都是以"x"开头,后面是操作符”>=“或”<=",再后面是一个整型常量。当一行中包含两个比较时,第一个总是">="。
除了最后一行之外,所有行都由运算符"||“结尾。一行中的每个符号都由一个空格隔开(”>=“是一个符号,”<="同理),行首和行尾没有多余的空格。

输出要求

输出包含若干行,格式与输入格式相同,按照表达式中数字的大小从小到大输出。对所有整数x产生与输入表达式相同的比较结果,在其文本中包含尽可能少的行数。
注意,题目默认x>=-32768 && x<=32767。特别地,如果表达式对[-32768,32767]内所有整数都为真,则写一行单词"true"。如果表达式对[-32768,32767]内所有整数都为假,则写一行单词"false"。
如果某个区间内只包含一个常数c,则输出"x >= c && x <=c"。

样例1

样例输入:

x >= 3 && x <= 5 ||
x >= 8 && x <= 11 ||
x >= 7 ||
x <= 0
样例输出:

x <= 0 ||
x >= 3 && x <= 5 ||
x >= 7
样例2

样例输入:

x >= 5 && x <= 3
样例输出:

false
样例3

样例输入:

x <= 5 ||
x >= -3
样例输出:

true
样例4

样例输入:

x >= -32768 && x <= 0 ||
x <= 0
样例输出:

x <= 0
数据范围
对于30%的数据,1<=T<=100
对于100%的数据,1<=T<=1000,所有数据绝对值<=100000

#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
#include <cstring>
#include <queue>

#define MIN -32768
#define MAX 32767

using std::set;
using std::pair;
using std::make_pair;
using std::queue;

set<pair<int, int> > area;
typedef pair<int, int> pr;

void orLimit(int left, int right)
{
    // printf("s+ [%d, %d]", left, right);
    queue<pr> q;
    for (set<pr>::iterator it = area.begin(); it != area.end(); it++)
    {
        if (it->second < left - 1) continue;
        if (it->first > right + 1) break;
        left = std::min(it->first, left);
        right = std::max(it->second, right);
        // area.erase(it);
        q.push(make_pair(it->first, it->second));
    }

    while (!q.empty())
    {
        area.erase(area.find(q.front()));
        q.pop();
    }
    area.insert(make_pair(left, right));
    // printf(" +s\n");
}

void read(char *s)
{
    std::cin.getline(s, 1800);
}

int main()
{
    while(true)
    {
        char in[1800];
        int num;
        int l = -1, r = -1;
        int g;
        char x[3], op1[3], mid[3], xx[2], op2[3], end[3];
        bool exit = false;
        read(in);

        g = sscanf(in, "%s %s %d %s %s %s %d %s", x, op1, &l, mid, xx, op2, &r, end);
        if (g < 1)
        {
            area.insert(make_pair(MIN, MAX));
            break;
        }
        if (g <= 4)
        {
            exit = g != 4;
            if (op1[0] == '<')
            {
                r = l;
                l = MIN;
            }
            else
            {
                r = MAX;
            }
        }
        else
        {
            exit = g != 8;
        }
        
        if (l <= r)
            orLimit(l, r);

        if (exit) break;
    }

    if(area.size() == 0)
    {
        printf("false\n");
    }
    else
    {
        int aaa = 0;
        for (set<pr>::iterator it = area.begin(); it != area.end(); it++)
        {
            if (it->first <= MIN && it->second >= MAX)
            {
                printf("true");
            }
            else if (it->first <= MIN)
            {
                printf("x <= %d", it->second);
            }
            else if (it->second >= MAX)
            {
                printf("x >= %d", it->first);
            }
            else
            {
                printf("x >= %d && x <= %d", it->first, it->second);
            }
            if (aaa != area.size() - 1)
            {
                printf(" ||\n");
            }
            else
            {
                printf("\n");
            }
            aaa++;
        }
    }

    return 0;
}

在这里插入图片描述
逻辑表达式
将输入的各个表达式按照分隔符分割;结构体储存各个左右端点
按照左区间排序,不断合并相交的区间;不相交则从下一个区间开始。
最后所有交集输出即可
模测之后助教有讲解过代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值