Hello 2018 E

题意

告诉你 x y z x、y、z ,以及 ! & ! 、|、\& 元素符和括号搭配,组成想要的八位二进制串。

题解

第一次见到用 s t r i n g string 作为数组进行转移的,涨知识。
考虑优先级。
对于一个运算符,两个数都应该大于其优先级。
所以我们设立三个数组,分别代表最低优先级即 | ,中等 & \& ,最高 ! ! 和括号。
x y z x、y、z 也可以。
数组表达的意思就是,最后一次运算是以什么结尾的。
因为只有在低优先级进行高优先运算符运算的时候才需要加括号,所以 ! ! 可以和括号看成一个。

转移的时候,因为不确定顺序,所以我们进行多次转移,知道无法进行有效转移为止。
网上写了简洁版的,就是转移的过程中不断取最小。
我写了比较暴力的转移,就是单纯分三种情况,暴力转移。
显然最低优先级的可以被高优先级的随意分配,所以是 9 9 种转移。
中等的是 4 4 种。
高等的自己转自己 1 1 种。
低级的加括号是 2 2

因为要求长度最小之后保证字典序最小,所以不能直接进行字符串比较。

#include<bits/stdc++.h>
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define sf(x) scanf("%d",&x)
typedef long long ll;
using namespace std;

const ll mod = 998244353;
const int maxn = 2e5+500;

int n;
string E[256],T[256],F[256];//|| & !

bool flag=true;

void update(string &A,string B){
    if(A=="")A=B,flag=1;
    else{
        if(A.size()>B.size())A=B,flag=1;
        else if(A.size()==B.size()&&A>B)A=B,flag=1;
    }
}

void slove(){
    int x=0,y=0,z=0;
    for(int i=0;i<8;i++)if(i/4)x|=1<<i;F[x]="x";
    for(int i=0;i<8;i++)if((i/2)%2)y|=1<<i;F[y]="y";
    for(int i=0;i<8;i++)if(i%2)z|=1<<i;F[z]="z";
    while(flag){
        flag=0;
        for(int i=0;i<256;i++){
            for(int j=0;j<256;j++){
                if(E[i].size()&&E[j].size())update(E[i|j],E[i]+'|'+E[j]);
                if(E[i].size()&&T[j].size())update(E[i|j],E[i]+'|'+T[j]);
                if(T[i].size()&&E[j].size())update(E[i|j],T[i]+'|'+E[j]);
                if(E[i].size()&&F[j].size())update(E[i|j],E[i]+'|'+F[j]);
                if(F[i].size()&&E[j].size())update(E[i|j],F[i]+'|'+E[j]);
                if(T[i].size()&&T[j].size())update(E[i|j],T[i]+'|'+T[j]);
                if(F[i].size()&&T[j].size())update(E[i|j],F[i]+'|'+T[j]);
                if(T[i].size()&&F[j].size())update(E[i|j],T[i]+'|'+F[j]);
                if(F[i].size()&&F[j].size())update(E[i|j],F[i]+'|'+F[j]);
            }
        }
       // cout<<E[248]<<"->"<<F[248]<<"->"<<T[248]<<endl;
        for(int i=0;i<256;i++){
            for(int j=0;j<256;j++){
                if(T[i].size()&&T[j].size())update(T[i&j],T[i]+'&'+T[j]);
                if(F[i].size()&&T[j].size())update(T[i&j],F[i]+'&'+T[j]);
                if(T[i].size()&&F[j].size())update(T[i&j],T[i]+'&'+F[j]);
                if(F[i].size()&&F[j].size())update(T[i&j],F[i]+'&'+F[j]);
            }
        }
        //cout<<E[248]<<"->"<<F[248]<<"->"<<T[248]<<endl;
        for(int i=0;i<256;i++)if(E[i]!="")update(F[i],'('+E[i]+')');//变为最高优先级
        for(int i=0;i<256;i++)if(T[i]!="")update(F[i],'('+T[i]+')');//变为最高优先级
        for(int i=0;i<256;i++)if(F[i]!="")update(F[i^255],'!'+F[i]);//运算的字符串的优先级必须大于等于运算符
        //for(int i=0;i<256;i++)cout<<i<<" "<<E[i]<<" "<<T[i]<<" "<<F[i]<<endl;
        //puts("?");
        if(!flag)break;
    }
}

int main(){
    slove();
    cin>>n;
    FOR(i,1,n){
        string st;cin>>st;
        int now=0;
        for(int j=0;j<8;j++){
            if(st[j]=='1')now|=1<<j;
        }
        string str;
       //cout<<now<<endl;
        update(str,E[now]);
        update(str,F[now]);
        update(str,T[now]);
        cout<<str<<endl;
    }
}

发布了203 篇原创文章 · 获赞 17 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/mxYlulu/article/details/104272216
今日推荐