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; ...
随机推荐
- 简单TCP代码
服务器: SOCKET s; s = ::socket(AF_INET,SOCK_STREAM,); sockaddr_in addr; addr.sin_family = AF_INET; addr ...
- TCP报文到达确认(ACK)机制
TCP数据包中的序列号(Sequence Number)不是以报文段来进行编号的,而是将连接生存周期内传输的所有数据当作一个字节流,序列号就是整个字节流中每个字节的编号.一个TCP数据包中包含多个字节 ...
- cogs——49. 跳马问题
49. 跳马问题 水题 dfs裸基础 #include<cstdio> using namespace std; ]={,,,,}, ans,my[]={,-,,-,}; inline v ...
- POJ-2135-Farm Tour(最大费用最小流)模板
Farm Tour POJ - 2135 When FJ's friends visit him on the farm, he likes to show them around. His farm ...
- Coefficient Computation (大整数、Java解决)
Coefficient Computation UVALive8265 题意:计算组合数C(n,k)的值并将值按给定的进制输出. 思路:Java大整数类硬上. PS:刚刚学完Java的大整数类,结果却 ...
- 00.continue break return的使用场景
continue continue 语句跳出本次循环,而break跳出整个循环. continue 语句用来告诉Python跳过当前循环的剩余语句,然后继续进行下一轮循环. continue语句用在w ...
- 【模板】Hash
洛谷3370 这题煞笔的吧QAQ......排序去重或者Map都可以 #include<cstdio> #include<map> #include<string> ...
- PAT 1109 Group Photo
Formation is very important when taking a group photo. Given the rules of forming K rows with N peop ...
- 【codeforces 515B】Drazil and His Happy Friends
[题目链接]:http://codeforces.com/contest/515/problem/B [题意] 第i天选择第i%n个男生,第i%m个女生,让他们一起去吃饭; 只要这一对中有一个人是开心 ...
- App后台开发运维和架构实践学习总结(2)——RESTful API设计技巧
前言 移动互联网时代,RESTful API成为越来越重要的移动端和服务器端交互的形式.尤其是在很多互联网公司或者传统行业拥抱移动互联网的时候,一套设计良好的Restful API能够帮助互联网产品支 ...