习题: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;
}
posted @ 2020-08-09 16:02  loney_s  阅读(160)  评论(0)    收藏  举报