[CF913E]Logical Expression

Logical Expression

题解

看到这题应该很容易想到暴力的,毕竟只有256种情况

但是,由于这是状压的题,必须用状压来做。否则T**M*E***又会***

定义dp_{i,j}为进行了i次操作,x,y,z的值的情况为j时的字典序最小表达式。

但我们很快就发现,因为有字典序的限制,并不是每一层都要加括号,非运算,或运算与与运算本身的优先级是不一样的。所以原本的dp法有问题。

重新定义dp_{i,j,k},前两维含义与之前一样,k表示当前式子的优先级。

优先级0表示,存在一个或运算未在括号内进行,

优先级1表示,不存在或运算未在括号内进行,但存在一个与运算在括内进行,

优先级2表示,不存在或运算与与运算未在括号内进行。

至于非运算,直接加在式子外即可,毕竟它优先级最高。

初始状态也很好想,dp_{0,(00001111)_{2},2}="x",\, dp_{0,(00110011)_{2},2}="y",\, dp_{0,(01010101)_{2},2}="z"\,

转移方法更好想,直接把符号加上即可。

源码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF=0x7f7f7f7f;
const LL mo=1e9+7;
typedef pair<LL,LL> pii;
int n,a[10];
string dp[15][300][3];
void upd(string& trg,string org){
	if(trg.empty())trg=org;
	else if(org.size()<trg.size())trg=org;
	else if(org<trg&&org.size()==trg.size())trg=org;
}
signed main(){
	dp[0][0b00001111][2]='x';
	dp[0][0b00110011][2]='y';
	dp[0][0b01010101][2]='z';
	for(int i=0;i<9;i++){
		for(int j=0;j<(1<<8);j++){
			if(!dp[i][j][0].empty())upd(dp[i+1][j][0],dp[i][j][0]);
			if(!dp[i][j][1].empty())upd(dp[i+1][j][1],dp[i][j][1]);
			if(!dp[i][j][2].empty())upd(dp[i+1][j][2],dp[i][j][2]);
			if(!dp[i][j][0].empty())upd(dp[i+1][j][2],"("+dp[i][j][0]+")");
			if(!dp[i][j][1].empty())upd(dp[i+1][j][2],"("+dp[i][j][1]+")");
			if(!dp[i][j][2].empty())upd(dp[i+1][j][2],"("+dp[i][j][2]+")");
			if(!dp[i][j][2].empty())upd(dp[i+1][(0b11111111)^j][2],"!"+dp[i][j][2]);
		}
		for(int j=0;j<(1<<8);j++)
			for(int k=0;k<(1<<8);k++){
				if(!dp[i][j][0].empty()&&!dp[i][k][1].empty())upd(dp[i+1][j|k][0],dp[i][j][0]+"|"+dp[i][k][1]);
				if(!dp[i][j][0].empty()&&!dp[i][k][2].empty())upd(dp[i+1][j|k][0],dp[i][j][0]+"|"+dp[i][k][2]);
				if(!dp[i][j][1].empty()&&!dp[i][k][1].empty())upd(dp[i+1][j|k][0],dp[i][j][1]+"|"+dp[i][k][1]);
				if(!dp[i][j][1].empty()&&!dp[i][k][2].empty())upd(dp[i+1][j|k][0],dp[i][j][1]+"|"+dp[i][k][2]);
				if(!dp[i][j][2].empty()&&!dp[i][k][1].empty())upd(dp[i+1][j|k][0],dp[i][j][2]+"|"+dp[i][k][1]);
				if(!dp[i][j][2].empty()&&!dp[i][k][2].empty())upd(dp[i+1][j|k][0],dp[i][j][2]+"|"+dp[i][k][2]);
				if(!dp[i][j][1].empty()&&!dp[i][k][2].empty())upd(dp[i+1][j&k][1],dp[i][j][1]+"&"+dp[i][k][2]);
				if(!dp[i][j][2].empty()&&!dp[i][k][2].empty())upd(dp[i+1][j&k][1],dp[i][j][2]+"&"+dp[i][k][2]);
			}
	}
	/*for(int i=0;i<(1<<8);i++){
		string ans="";
		upd(ans,dp[9][i][0]);
		upd(ans,dp[9][i][1]);
		upd(ans,dp[9][i][2]);
		cout<<i<<":"<<ans<<endl;
	}*/
	scanf("%d",&n);
	while(n--){
		for(int i=0;i<8;i++)scanf("%1d",&a[i]);
		int sum=0;for(int i=0;i<8;i++)sum<<=1,sum+=a[i];
		string ans="";
		upd(ans,dp[9][sum][0]);
		upd(ans,dp[9][sum][1]);
		upd(ans,dp[9][sum][2]);
		cout<<ans<<endl;
	}
	return 0;
}

谢谢!!!

posted @ 2020-08-09 16:28  StaroForgin  阅读(12)  评论(0)    收藏  举报  来源