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; ...
随机推荐
- js分页插件
//分页插件1function showView(option) { //参数定义id,页容量,当前页,总数,页总数 var id = option.id, pageSiz ...
- mysql命令行导出数据
1. 包含表头 mysql -h${1} -P${2} -u${3} -p${4} -Dpom_${5} --default-character-set=utf8 -B -e > result. ...
- 扩增子图表解读3热图:差异菌、OTU及功能
热图是使用颜色来展示数值矩阵的图形.通常还会结合行.列的聚类分析,以表达实验数据多方面的结果. 热图在生物学领域应用广泛,尤其在高通量测序的结果展示中很流行,如样品-基因表达,样品-OTU相对丰度矩 ...
- jenkins配置邮件通知
参考: https://www.cnblogs.com/imyalost/p/8781759.html 谢谢大佬~
- 【centOS7】Jenkins安装--漫漫踩坑路
安装步骤: https://www.cnblogs.com/h--d/p/5673085.html 安装后遇到的问题及解决办法: jenkins的admin用户的初始密码路径 https://blog ...
- vue项目中使用百度地图的方法
1.在百度地图申请密钥: http://lbsyun.baidu.com/ 将 <script type="text/javascript" src="http: ...
- Java中字符串的常用属性与方法
•字符串常用的属性 string.length()————>返回字符串的长度,int类型. •字符串常用的方法 String.contains(";")——————>判 ...
- 最基础的rpm命令
rpm -ivh package.rpm 安装一个rpm包 rpm -ivh --nodeeps package.rpm 安装一个rpm包而忽略依赖关系警告 rpm -U package.rpm 更新 ...
- [测试工具]----iperf
iperf https://sourceforge.net/projects/iperf/ http://downloads.es.net/pub/iperf/ https://github.com/ ...
- vs2015 配置 cplex
首先设置模式为Release, 根据软件选择x86或x64 附加库目录(链接器 - 常规) C:\Program Files\IBM\ILOG\CPLEX_Studio128\cplex\lib\x6 ...