zoukankan      html  css  js  c++  java
  • Codeforces Hello 2018 E题Logical Expression dp+最短路 好题

    j题目链接: http://codeforces.com/contest/913/problem/E

    题意:

     给你x,y,z三个变量,与&   或|  非!  括号()   四种运算符,规定括号和非优先级最高,其次与&,最后或|。

     对于输入的真值表,输出最小字典序的逻辑表达式

    挺难想的。关键点在于怎么定义状态并利用已有状态更新出新状态,并处理优先级问题。

    状态转移:

    对于两个表达式A1,A2及其真值表T1,T2,若没有优先级的问题,A1&A2的真值表为T1&T2,A1|A2的真值表为T1|T2,!A1的真值表为~T1。

    为了解决优先级的问题,按优先级不同进行分类,以dp[i][j]存储真值表为i,优先级为j的字典序最小逻辑表达式。,操作只在相同优先级表达式之间进行,维护一个优先级之间的升降通道。

    模仿dijkstra的思想,维护一个序列,每次选出字典序最小的表达式作为A1并pop掉,在dp[i][j]中枚举A2进行更新操作。

    真值表共有2^(2^3)共256种,优先级共3种可能。状态数n=3*256。

    每种状态至多作为A1被考虑一次,枚举A2O(n),综合得算法复杂度O(n^2)

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int FULL=0xFF;
    bool cmp(string a,string b)
    {
        if(a.length()==b.length()) return a<b;
        return a.length()<b.length();
    }
    struct Expression
    {
        int table;
        int level;
        string exp;
        Expression(int a,int b,string c) {table=a;level=b;exp=c;}
        bool operator < (const Expression& b)const
        {
            if(b.exp==exp)
            {
                if(level!=b.level) return level<b.level;
                return table<b.table;
            }
            return cmp(exp,b.exp);
        }
    };
    set<Expression> q;
    string dp[1<<8][3];
    void add(int level,int state,string s)
    {
        if(dp[state][level].empty()||cmp(s,dp[state][level]))
        {
            dp[state][level]=s;
            Expression e(state,level,s);
            q.insert(e);
        }
    }
    void pre()
    {
        int X_table=0,Y_table=0,Z_table=0;
        for(int i=0;i<8;++i)
        {
            if(i&(1<<2)) X_table+=(1<<i);
            if(i&(1<<1)) Y_table+=(1<<i);
            if(i&(1<<0)) Z_table+=(1<<i);
        }
        add(2,X_table,"x");
        add(2,Y_table,"y");
        add(2,Z_table,"z");
        while(!q.empty())
        {
            set<Expression>:: iterator it;
            it=q.begin();
            Expression u=*it;
            q.erase(it);
          //  auto u=*q.begin();
          //  q.erase(q.begin());
            if(u.level==2)
            {
                add(2,u.table^FULL,"!"+u.exp);
                add(1,u.table,u.exp);
            }
            if(u.level==1)
            {
                for(int i=0;i<=FULL;++i)
                {
                    if(!dp[i][1].empty())
                    {
                        add(1,i&u.table,dp[i][1]+"&"+u.exp);
                        add(1,i&u.table,u.exp+"&"+dp[i][1]);
                    }
                }
                add(2,u.table,"("+u.exp+")");
                add(0,u.table,u.exp);
            }
            if(u.level==0)
            {
                for(int i=0;i<=FULL;++i)
                {
                    if(!dp[i][0].empty())
                    {
                        add(0,i|u.table,dp[i][0]+"|"+u.exp);
                        add(0,i|u.table,u.exp+"|"+dp[i][0]);
                    }
                }
                add(2,u.table,"("+u.exp+")");
            }
        }
    }
    void work()
    {
        int n;
        scanf("%d",&n);
        string s;
        for(int i=1;i<=n;++i)
        {
            cin>>s;
           // cout<<"s="<<s<<endl;
            int state=0;
            for(int j=0;j<8;++j)
            {
                if(s[j]=='1') state|=(1<<j);
            }
            //printf("state=%d
    ",state);
            cout<<dp[state][0]<<endl;
        }
    }
    int main()
    {
        pre();
        work();
        return 0;
    }
  • 相关阅读:
    程序片段--2的乘方
    Set、Map集合、栈、队列
    Map迭代(六种)
    Struts2标签--控制标签
    线性表
    数据结构笔记(1)
    spingMVC问题小结
    《浪潮之巅》十四章笔记
    《浪潮之巅》十三章笔记
    《浪潮之巅》十二章笔记
  • 原文地址:https://www.cnblogs.com/zhixingr/p/8343835.html
Copyright © 2011-2022 走看看