[CF913E]Logical Expression

220 篇文章 2 订阅
23 篇文章 0 订阅

题目

传送门 to luogu

思路

明明是个™暴搜题。复杂度证不了。

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值