习题:Logical Expression(状压DP)
题目
思路
看到这道题,应该下意识的会设\(dp[i]\)最优方案能构成i
但是转移就很麻烦,主要是要考虑优先级的问题
这里我们人为的将其分成3个优先级,这里的优先级主要是为了考虑括号和!的问题
设\(f,g,h\)三种函数
其中f和!,()同级,g和&同级,h和|同级
对于f,只需要考虑h加上括号或者!转移过去
对于g,考虑f下来的,和自身&的转移
对于h,考虑g下来的,和自身|的转移
代码
#include<iostream>
using namespace std;
int n;
string dp[4][(1<<8)];
bool cmp(const string &a,const string &b)
{
if(a=="")
return 1;
return a.length()==b.length()?a>b:a.length()>b.length();
}
int main()
{
dp[3][240]="x";
dp[3][204]="y";
dp[3][170]="z";
while(1)
{
bool f=0;
for(int i=0;i<(1<<8);i++)
{
if(dp[1][i]!=""&&cmp(dp[3][i],"("+dp[1][i]+")"))
{
dp[3][i]="("+dp[1][i]+")";
f=1;
}
if(dp[3][i]!=""&&cmp(dp[3][i^(1<<8)-1],"!"+dp[3][i]))
{
dp[3][i^((1<<8)-1)]="!"+dp[3][i];
f=1;
}
}
for(int i=0;i<(1<<8);i++)
{
if(cmp(dp[2][i],dp[3][i])&&dp[3][i]!="")
{
dp[2][i]=dp[3][i];
f=1;
}
for(int j=0;j<(1<<8);j++)
{
if(cmp(dp[2][i&j],dp[2][i]+"&"+dp[2][j])&&dp[2][i]!=""&&dp[2][j]!="")
{
dp[2][i&j]=dp[2][i]+"&"+dp[2][j];
f=1;
}
}
}
for(int i=0;i<(1<<8);i++)
{
if(cmp(dp[1][i],dp[2][i])&&dp[2][i]!="")
{
dp[1][i]=dp[2][i];
f=1;
}
for(int j=0;j<(1<<8);j++)
{
if(cmp(dp[1][i|j],dp[1][i]+"|"+dp[1][j])&&dp[1][i]!=""&&dp[1][j]!="")
{
dp[1][i|j]=dp[1][i]+"|"+dp[1][j];
f=1;
}
}
}
if(f==0)
break;
}
cin>>n;
for(int i=1;i<=n;i++)
{
string a;
int now=0;
cin>>a;
for(int j=7;j>=0;j--)
now=(now<<1)+a[j]-'0';
cout<<dp[1][now]<<endl;
}
return 0;
}

浙公网安备 33010602011771号