time limit per test
3 seconds
memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a boolean function of three variables which is defined by its truth table. You need to find an expression of minimum length that equals to this function. The expression may consist of:

  • Operation AND ('&', ASCII code 38)
  • Operation OR ('|', ASCII code 124)
  • Operation NOT ('!', ASCII code 33)
  • Variables x, y and z (ASCII codes 120-122)
  • Parentheses ('(', ASCII code 40, and ')', ASCII code 41)

If more than one expression of minimum length exists, you should find the lexicographically smallest one.

Operations have standard priority. NOT has the highest priority, then AND goes, and OR has the lowest priority. The expression should satisfy the following grammar:

E ::= E '|' T | T

T ::= T '&' F | F

F ::= '!' F | '(' E ')' | 'x' | 'y' | 'z'

Input

The first line contains one integer n — the number of functions in the input (1 ≤ n ≤ 10 000).

The following n lines contain descriptions of functions, the i-th of them contains a string of length 8 that consists of digits 0 and 1 — the truth table of the i-th function. The digit on position j (0 ≤ j < 8) equals to the value of the function in case of  and .

Output

You should output n lines, the i-th line should contain the expression of minimum length which equals to the i-th function. If there is more than one such expression, output the lexicographically smallest of them. Expressions should satisfy the given grammar and shouldn't contain white spaces.

Example
input
4
00110011
00000111
11110000
00011111
output
y
(y|z)&x
!x
x|y&z
Note

The truth table for the second function:

大意:给出三个八位二进制数x,y,z,允许使用!、&、| 运算,也可以加括号。

给出N个数(都是八位二进制数),求用x、y、z组成的最短的表达式中字典序最小的。

题解:考场上我肯定做不出来的,这题又是一个很奇怪的dp

由于表达式间有明确的优劣关系,可以直接用表达式字符串作为状态。

E[i]表示最后进行的运算是 | 的值为 i 的表达式

T[i]表示最后进行的运算是 & 的值为 i 的表达式

F[i]表示最后进行的运算是 ! 的值为 i 的表达式

最后进行的是括号运算的表达式性质与F相似,归为一类。

起始状态("x","y","z")表达式性质与F相似,归为一类。

那么状态转移怎么做?

先上图

1、2是题目中提到的转移方式,5应该不用解释

关键在于3、4,思考:F[i]的性质一定满足T[i]的性质,T[i]的性质一定满足E[i]的性质。(这需要联系运算符优先级思考)

所以把F[i]当做T[i],T[i]当做E[i]来用稳赚不亏

这样,!操作只需要对F做就行了,因为F可以向T和E传递。

需要注意的是转移顺序:

1一定在2之前。

3一定在4之前。

不然~~~~~~~时间复杂度常数会大一点(其实也没事)。

这样五种转移为一轮,当整整一轮没有做有效更新时结束就行了。

/*
Welcome Hacking
Wish You High Rating
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
int read(){
int xx=0,ff=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')ff=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){xx=(xx<<3)+(xx<<1)+ch-'0';ch=getchar();}
return xx*ff;
}
const int X=15,Y=51,Z=85;
string E[256],T[256],F[256];//E:| T:& F:!
bool flag;
void upd(string &A,const string&B){
if(A==""){
A=B;
flag=1;
return;
}
int t1=A.size(),t2=B.size();
if(t1>t2)
A=B,flag=1;
else if(t1==t2)
if(A>B)
A=B,flag=1;
}
int main(){
//freopen("in","r",stdin);
//freopen("out","w",stdout);
F[X]='x',F[Y]='y',F[Z]='z';
while(1){
flag=0;
for(int i=0;i<=255;i++)
if(T[i]!="")
for(int j=0;j<=255;j++)
if(F[j]!="")
upd(T[i&j],T[i]+'&'+F[j]);
for(int i=0;i<=255;i++)
if(E[i]!="")
for(int j=0;j<=255;j++)
if(T[j]!="")
upd(E[i|j],E[i]+'|'+T[j]);
for(int i=0;i<=255;i++)
if(E[i]!="")
upd(F[i],'('+E[i]+')');
for(int i=0;i<=255;i++)
if(F[i]!="")
upd(T[i],F[i]);
for(int i=0;i<=255;i++)
if(T[i]!="")
upd(E[i],T[i]);
for(int i=0;i<=255;i++)
if(F[i]!="")
upd(F[i^255],'!'+F[i]);
if(!flag)
break;
}
int T,N;
char s[10];
T=read();
while(T--){
gets(s);
N=0;
for(int i=0;i<=7;i++)
N=(N<<1)+s[i]-'0';
cout<<E[N]<<endl;
}
return 0;
}

  最短路+记录路径应该也可做,但是~~~应该很麻烦。

codeforces 931E Logical Expression dp的更多相关文章

  1. Codeforces Hello 2018 E题Logical Expression dp+最短路 好题

    j题目链接: http://codeforces.com/contest/913/problem/E 题意: 给你x,y,z三个变量,与&   或|  非!  括号()   四种运算符,规定括 ...

  2. 【CodeForces】913 E. Logical Expression

    [题目]E. Logical Expression [题意]令x=11110000(2),y=11001100(2),z=10101010(2),n次询问,每次要求用[与][或][非][括号]构成含至 ...

  3. [Codeforces 1201D]Treasure Hunting(DP)

    [Codeforces 1201D]Treasure Hunting(DP) 题面 有一个n*m的方格,方格上有k个宝藏,一个人从(1,1)出发,可以向左或者向右走,但不能向下走.给出q个列,在这些列 ...

  4. Codeforces 1461F - Mathematical Expression(分类讨论+找性质+dp)

    现场 1 小时 44 分钟过掉此题,祭之 大力分类讨论. 如果 \(|s|=1\),那么显然所有位置都只能填上这个字符,因为你只能这么填. scanf("%d",&n);m ...

  5. 2018.12.12 codeforces 931E. Game with String(概率dp)

    传送门 感觉这题难点在读懂题. 题目简述:给你一个字符串s,设将其向左平移k个单位之后的字符串为t,现在告诉你t的第一个字符,然后你可以另外得知t的任意一个字符,求用最优策略猜对k的概率. 解析: 预 ...

  6. codeforces Hill Number 数位dp

    http://www.codeforces.com/gym/100827/attachments Hill Number Time Limits:  5000 MS   Memory Limits: ...

  7. codeforces Educational Codeforces Round 16-E(DP)

    题目链接:http://codeforces.com/contest/710/problem/E 题意:开始文本为空,可以选择话费时间x输入或删除一个字符,也可以选择复制并粘贴一串字符(即长度变为两倍 ...

  8. codeforces #round363 div2.C-Vacations (DP)

    题目链接:http://codeforces.com/contest/699/problem/C dp[i][j]表示第i天做事情j所得到最小的假期,j=0,1,2. #include<bits ...

  9. codeforces round367 div2.C (DP)

    题目链接:http://codeforces.com/contest/706/problem/C #include<bits/stdc++.h> using namespace std; ...

随机推荐

  1. 使用 RxJava 的正确姿势

    最近在使用 RxJava 时遇到了一些比较诡异的问题,排查的过程中做了点研究,发现平时大家的用法多多少少都有些问题.有些地方存在隐患,有些用法不够简练,我把这些问题简单做一下分类和总结,供大家参考. ...

  2. windows server2003 多用户登陆问题解决办法

    windows server2003 多用户登陆问题解决办法 Windows Server远程登陆默认情况下只允许同时有两个用户登陆,超过两个用户会提示"超出最大连接数". 要解决 ...

  3. linux启动时开启screen

    编辑/etc/rc.local 添加 su - ubuntu -c 'screen -dmS ss zserver -p /etc/config'

  4. Makefile精髓篇【转】

    什么是makefile?或许非常多Winodws的程序猿都不知道这个东西,由于那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序猿,makefile还是 ...

  5. PHP操作Redis相关函数

    String数据类型 $redis->set('key','TK'); $redis->set('number','1'); //设置值 $redis->setex('key',5, ...

  6. -moz、-ms、-webkit

    1.-moz代表firefox浏览器私有属性 2.-ms代表IE浏览器私有属性 3.-webkit代表safari.chrome私有属性 需要设置这个的样式: transform,border-rad ...

  7. 网络爬虫 robots协议 robots.txt

    网络爬虫 网络爬虫是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成.传统爬虫从一个或若干初始网页的URL开始,获得初始网页上的URL,在抓取网页的过程中,不断从当前页面上 ...

  8. linux 的sed命令解释 sed ':t;N;s/\n/,/;b t' 将换行符换成逗号

    linux 的sed命令解释 sed ':t;N;s/\n/,/;b t' 将换行符换成逗号 实现的功能是吧换行符换成逗号了,自己试验过. 求解释,:t N b t 都是什么意思??? :t 定义la ...

  9. gitlab分享项目到其它组

    1. 找到以下页面(管理员权限),随便点入一个项目 2. 点击edit编辑 3.点击members 4. 查看是否分享成功

  10. linux下的vi的使用方法

    vi的使用: 一般指令模式: vi打开一个文件就直接进入一般指令模式,可以进行删除.复制.粘贴.但是不可以对文件的内容进行修改. 常用命令: ctrl + f 向下移动一页 ctrl + b 向上移动 ...