codeforces 931E Logical Expression dp
256 megabytes
standard input
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'
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
.
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.
4
00110011
00000111
11110000
00011111
y
(y|z)&x
!x
x|y&z
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的更多相关文章
- Codeforces Hello 2018 E题Logical Expression dp+最短路 好题
j题目链接: http://codeforces.com/contest/913/problem/E 题意: 给你x,y,z三个变量,与& 或| 非! 括号() 四种运算符,规定括 ...
- 【CodeForces】913 E. Logical Expression
[题目]E. Logical Expression [题意]令x=11110000(2),y=11001100(2),z=10101010(2),n次询问,每次要求用[与][或][非][括号]构成含至 ...
- [Codeforces 1201D]Treasure Hunting(DP)
[Codeforces 1201D]Treasure Hunting(DP) 题面 有一个n*m的方格,方格上有k个宝藏,一个人从(1,1)出发,可以向左或者向右走,但不能向下走.给出q个列,在这些列 ...
- Codeforces 1461F - Mathematical Expression(分类讨论+找性质+dp)
现场 1 小时 44 分钟过掉此题,祭之 大力分类讨论. 如果 \(|s|=1\),那么显然所有位置都只能填上这个字符,因为你只能这么填. scanf("%d",&n);m ...
- 2018.12.12 codeforces 931E. Game with String(概率dp)
传送门 感觉这题难点在读懂题. 题目简述:给你一个字符串s,设将其向左平移k个单位之后的字符串为t,现在告诉你t的第一个字符,然后你可以另外得知t的任意一个字符,求用最优策略猜对k的概率. 解析: 预 ...
- codeforces Hill Number 数位dp
http://www.codeforces.com/gym/100827/attachments Hill Number Time Limits: 5000 MS Memory Limits: ...
- codeforces Educational Codeforces Round 16-E(DP)
题目链接:http://codeforces.com/contest/710/problem/E 题意:开始文本为空,可以选择话费时间x输入或删除一个字符,也可以选择复制并粘贴一串字符(即长度变为两倍 ...
- codeforces #round363 div2.C-Vacations (DP)
题目链接:http://codeforces.com/contest/699/problem/C dp[i][j]表示第i天做事情j所得到最小的假期,j=0,1,2. #include<bits ...
- codeforces round367 div2.C (DP)
题目链接:http://codeforces.com/contest/706/problem/C #include<bits/stdc++.h> using namespace std; ...
随机推荐
- ElasticSearch-5.21安装
环境 操作系统:Centos 6.5 X64 IP地址:192.168.56.100 JDK 环境: # java -version java version "1.8.0_121" ...
- CSS——精灵图与背景图片定位
精灵图产生背景: 1.网页上的每张图像都需要向服务器发送一次请求才能展现给用户.2.网页上的图像过多时,服务器就会频繁地接受和发送请求,大大降低页面的加载速度.为了有效地减少服务器接受和发送请求的次数 ...
- 大神所写的深度好文---Gradle 构建工具
什么是构建工具? 我们大家都知道 Gradle 是一种构建工具,那么什么是构建工具呢? 网上一大堆的文字解释我觉得很难理解,这里我以咱们 Android 开发来举个例子吧. 我们以前开发都是用 Ecl ...
- id 转 entity
object 是 entity原始的类 要使用id转化成entity要先将id.getobject 然后将这个值 (entity)转化成entity entity ent =id.getentity& ...
- Appium 教您完美win10安装Appium1.7.2支持win客户端自动化
参考内容: https://testerhome.com/topics/10193https://testerhome.com/topics/8223https://testerhome.com/to ...
- IO编程——复制一个文件中的内容到另一个文件
public class TestIO { public static void main(String[] args) { File inputFile = new File("a.txt ...
- 新手入门学习angular.js的心得体会
看了一天的angular.js,只要记住这是关于双向数据绑定 和单向数据绑定就可以,看看开发文档,短时间内还是可以直接入手的,看个人理解能力(我是小白). 这几天开始着手学习angularjs的有关知 ...
- 洛谷——P1572 计算分数
P1572 计算分数 模拟+字符串 注意有两位数的情况以及负数情况 #include<bits/stdc++.h> using namespace std; string s; ],b[] ...
- LNOI2019 退役记
Day -4 最近这两天智商有点不在线啊..得好好调整作息了,滚粗感++ 复习模板好啊 下午睡了一觉,智商似乎回来了一丢丢,滚粗感-- Day -3 智商略有回暖,滚粗感-- 明天有模拟赛,要加油啊 ...
- Spring 注解注入的几种方式(转)
平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程 ...