题目
思路
明明是个™暴搜题。复杂度证不了。
用 f ( S ) f(S) f(S) 表示,依照题目中输入的格式得到 S S S ,最优表达式为何。然后转移不动,因为运算符有优先级。
所以用 f ( S , i ) f(S,i) f(S,i) 表示优先级为 i i i 。具体看代码就行了。
代码
#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
template < class T >
void getMax(T&a,const T&b){if(a<b)a=b;}
template < class T >
void getMin(T&a,const T&b){if(b<a)a=b;}
// @return Whether %a is better than %b
bool cmp(const string &a,const string &b){
if(a.empty() or a.back() == '!' or
a[0] == '|' or a.back() == '|' or
a[0] == '&' or a.back() == '&')
return false;
if(b.empty()) return true;
if(a.size() != b.length())
return a.length() < b.size();
return a < b;
}
void updata(string &a,const string &b){
if(cmp(b,a)) a = b;
}
// 优先级规矩:最后一步是or则0,是and则1,其余则2
// 然后搞宽松点,改成优先级不低于k
string dp[1<<8][3];
// OPER[r] 是优先级为 r 的运算符(operator)
const string OPER[] = {"|","&","!"};
// @brief 给字符串加一对括号
string brace(const string &s){
if(s.empty()) return s; // 不合法
string t = "("; return t+s+")";
}
int main(){
dp[15][2] = "x", dp[51][2] = "y", dp[85][2] = "z";
for(int xez=0; xez<20; ++xez){ // 更新次数
for(int a=0; a<(1<<8); ++a){
updata(dp[255^a][2],OPER[2]+dp[a][2]);
for(int k=0; k<2; ++k) // 加()来升级
updata(dp[a][2],brace(dp[a][k]));
for(int k=2; k; --k) // 搞宽松些
updata(dp[a][k-1],dp[a][k]);
}
for(int a=0; a<(1<<8); ++a)
for(int b=0; b<(1<<8); ++b)
for(int k=0; k<2; ++k){
int now = (k)?(a&b):(a|b);
updata(dp[now][k],dp[a][k]
+OPER[k]+dp[b][k]);
}
}
for(int T=readint(); T; --T){
int now = 0;
for(int i=0; i<8; ++i)
now = (now<<1)^(getchar()-'0');
getchar(); // get '\n'
int len = dp[now][0].length();
for(int i=0; i<len; ++i)
putchar(dp[now][0][i]);
putchar('\n');
}
return 0;
}