卡诺图

如何用卡诺图化简带有约束条件的逻辑函数? 阅读详情

Abstract

HDU 4413 Logical Expression

乱搞 卡诺图

 

Body

Source

http://acm.hdu.edu.cn/showproblem.php?pid=4413

Description

给定N变量的所有2^N最小项,求一个符合所有最小项的最优美(长度最短的情况下字典序最小)的与或式。

Solution

天王还是太自信了……唉……

思路其实很简单。

复习一下卡诺图吧,考虑在卡诺图上圈一些圈,这些圈(可以重叠)覆盖且仅覆盖了所有为1的最小项,表达式就是这些圈项的或。

考虑卡诺图上的某个1,则所有覆盖这个1的非极大圈都不可能是最终答案的项,反证如下:假设某个覆盖这个1的非极大圈是最终答案的项,由于圈非极大,那么它一定属于某个极大圈,显然极大圈化简出的项长度比非极大圈要小。

于是所有可能的属于最终答案的项就是卡诺图上的所有极大圈。天王的错误就在于他只求出覆盖了每个1的最大(在所有极大圈中最优美)圈,这就相当于贪心,肯定是不对的(有可能某个非最大拼上其它的会更优)。这个地方不是很容易想明白,我也是试了一些数据才知道。

所以我们就对每个1求覆盖它的所有极大圈,得到一个极大圈集合(注意unique一下)。注意每个极大圈的表达式长度一定,所以先对每个极大圈求最优表达式(sort每个与项,比较函数是str1+str2<str2+str1)。然后就是用这些极大圈求最优覆盖,这个好像没什么好方法,只能搜。对极大圈集合排序一下可以加快搜索速度。

Code

代码是在天王那个wa的代码基础上改的,所以挺难看的……


#include<iostream>

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<string>
using namespace std;

typedef pair<string, int> node;
vector<node> ans;
bool vis[50];
int V[50];

bool cmp(string s1,string s2){
    return s1+s2<s2+s1;
}
bool cmp2(string s1,string s2){
    return s1+"+"+s2<s2+"+"+s1;
}
bool hmr(node a, node b) {
    if (a.second==b.second) {
        if (a.first.length()==b.first.length()) return a.first<b.first;
        return a.first.length()<b.first.length();
    }
    return a.second<b.second;
}

bool operator==(node a, node b) {
    return a.first==b.first && a.second==b.second;
}

string StInS(int s,int n,int ors){
    int i;
    vector<string> tmpAns;
    for (i=0;i<(1<<n);i++){
        if ((i&s)==(ors&s))
            if (V[i]==0) return "";
    }
    if (s==0) return "1";
    string tmp;
    for (i=0;i<n;i++) if (s&(1<<i)){
        tmp="";
        if (!(ors&(1<<i)))
            tmp+='-';
        tmp+=(char)(i+'A');
        tmpAns.push_back(tmp);
    }
    sort(tmpAns.begin(),tmpAns.end(),cmp);
    tmp="";
    for (i=0;i<tmpAns.size();i++)
        tmp+=tmpAns[i];
    return tmp;
}

void getans(int s, int n) {
    int i,j;
    int minsize = 0x3fff;
    vector<node> tmp;
    for (i=0;i<(1<<n);i++) {
        int ctrl=__builtin_popcount(i);
        if (ctrl>minsize) continue;
        string tans2=StInS(i,n,s);
        if (tans2.empty()) continue;
        if (ctrl<minsize) {
            minsize = ctrl;
            tmp.clear();
        }
        int res = 0;
        for (j = 0; j < 1<<n; ++j)
            if ((j&i)==(s&i)) res |= 1<<j;
        tmp.push_back(make_pair(tans2, res));
    }
    for (i = 0; i < tmp.size(); ++i)
        ans.push_back(tmp[i]);
}

int N, M;
int all;
int best;
bool use[64], ause[64];

void dfs(int i, int len, int cover) {
    if (len >= best) return;
    if (cover==all) {
        memcpy(ause, use, sizeof(use));
        best = len;
        return;
    }
    if (i==M) return;
    use[i] = 1;
    dfs(i+1, len+ans[i].first.length()+1, cover|ans[i].second);
    use[i] = 0;
    dfs(i+1, len, cover);
}

int main(){
    int i,s,j,v;
    int cas=0;
    for (;;){
        scanf("%d",&N);
        if (N==0) break;
        for (i=0;i<(1<<N);i++){
            s=0;
            vis[i] = 0;
            for (j=0;j<N;j++){
                scanf("%d",&v);
                s^=(v<<j);
            }
            scanf("%d",&V[s]);
        }
        ans.clear();
        memset(vis, 0, sizeof vis);
        all = 0;
        for (s = 0; s < 1<<N; ++s)
            if (V[s]){
                all |= 1<<s;
                getans(s, N);
            }
        if (ans.size()==0) {
            puts("-AA");
            continue;
        }
        if (ans[0].first[0]=='1') {
            puts("-A+A");
            continue;
        }
        sort(ans.begin(), ans.end(), hmr);
        M = unique(ans.begin(), ans.end())-ans.begin();
        sort(ans.begin(), ans.begin()+M);
        best = 0x3fffffff;
        memset(use, 0, sizeof use);
        memset(ause, 0, sizeof ause);
        dfs(0, 0, 0);
        vector<string> astr;
        for (i = 0; i < M; ++i)
            if (ause[i]) astr.push_back(ans[i].first);
        sort(astr.begin(), astr.end(), cmp2);
        string fin = astr[0];
        for (i = 1; i < astr.size(); ++i)
            fin += "+"+astr[i];
        cout << fin << '\n';
    }
    return 0;
}
卡诺图化简软件 有人上传过类似软件,但那版卡诺图化简结果不是最简的,且只能是四输入。本版卡诺图化简软件最多可以到8输入,且结果最简,可以有无关项 立即下载

相关推荐

Unipush2.0 App消息推送(在线+离线推送)

使用unipush2.0进行消息推送,包含在线跟离线

weixin_50251467的博客 3699

[报告]HDU 4413 Logical Expression

Abstract HDU 4413Logical Expression 乱搞 卡诺图 Body Source http://acm.hdu.edu.cn/showproblem.php?pid=4413 Description 给定N变量的所有2^N最小项,求一个符合所有最小项的最优美(长度最短的情况下字典序最小)的与或式。 Solution 天王还是太自信了……唉…… ...

weixin_33946020的博客 210

bugku渗透测试4-writeup

三、对这个主机进行全端口的扫描,发现存在22000 ssh端口,那么可以联想到时redis写入公钥来连接主机。又来了一个新的靶场,这个靶场打下来我觉得关键就是信息收集,走了很多的弯路。八、最后一个flag是要去看cms的数据库里面,这个数据库是sqlite。把这个数据库下载下来,登录密码是加密的,就直接用token。一、入口的漏洞是在登录的时候去抓包,修改action的值。六、没想到这个第一台机器的密码,在第二台里面。七、扫描第一台主机、使用之前的密码连接成功。获取最后一台主机的root密码。

vsdfbhsdhsdfh的博客 1297

一分钟掌握卡诺图化简法

卡诺图讲解

居安士的博客 5万+

学习使用turtlebot2——ROS上安装turtlebot2

安装环境:    安装Ubuntu 14.04版本和ROS Indigo    参考:http://wiki.ros.org/turtlebot/Tutorials安装步骤    有两种安装方法,一种直接的安装命令,另外一种源码编译安装,区别在于:直接安装命令是安装在电脑默认路径/opt/ros/indigo/share里面不便于更改代码,因为默认路径下文件一般有访问权限,无法直接更改,需要使用s...

weixin_42670641的博客 2531

AI影像组学在结直肠癌诊疗中的应用:从特征提取到临床决策

影像组学通过高通量计算从医学影像中提取定量特征,揭示肿瘤内部的微观生物学行为,这些特征反映了纹理异质性、形状不规则度等影像表型。其核心原理在于将图像数据转化为可分析的数字特征,结合机器学习算法进行模式识别,从而实现对疾病状态的精准预测。这一技术的价值在于能够无创、定量地评估肿瘤特性,为精准医疗提供关键支持。在临床实践中,AI驱动的影像组学模型广泛应用于结直肠癌的诊疗全链条,包括肿瘤良恶性鉴别、基因突变预测、治疗反应评估和预后分析等场景。通过整合影像组学特征与临床数据,可以构建预测模型,辅助医生进行更准确的诊

weixin_28295799的博客 409

HDLBITS 练习 卡诺图化简部分

hdlbits 卡诺图部分

dok12的博客 1万+

基于MATLAB/Simulink的四旋翼无人机PID控制与仿真(3)

《基于MATLAB/Simulink的四旋翼无人机PID控制与仿真》的第三篇,将为大家继续展示并完善控制与仿真模型。本文将在前文的基础上,完成控制环节增补、参数设置、测试等工作,在不考虑性能(低超调、快、准等)的前提下,保证系统对于一般输入(阶跃、斜坡)的响应稳定性。

jlx142857的博客 9321

卡诺图化简法

要注意的是画圈的时候可以重复,因为A+A=A,所以可以逻辑函数的标准形式中加任意其中一个最小项,其结果不会受到影响。但是要注意的是,在化简的时候,相邻两项不一定是唯一的,因为逻辑函数的最简形式不是唯一的。将逻辑式用卡诺图进行表示之后,就可以进行相邻相消了。

weixin_69143897的博客 1351

电化学-论文分享-NanoStat: An open source, fully wireless potentiostat

本文主要分享论文NanoStat: An open source, fully wireless potentiostat,并记录学习笔记。如果有条件,建议看原文最好。

分享技术笔记,希望对大家能够有一定的帮助,同时也通过归纳总结提升自己的个人能力。 2874

2021.02.23丨Virsorter2安装使用及答疑

最近项目比较多,又在学英语,写文章的时间少了很多。最近接到一个病毒组装的项目。用之前组装工具(ABYSS、SPAdes)都没有能够组装较为完整的scafford,今天介绍一款专门用于组装病毒的工具——Virsorter。 Virsorter最早版本发布于2015年,目前已经有了第二个版本。主要用于病毒的组装的注释。详细情况可以查看文章:https://peerj.com/articles/985/ 安装流程 安装文档: https://github.com/jiarong/VirSorter2/b

4835

数字电路——卡诺图

本文详细介绍卡诺图,认识卡诺图中几个相邻关系,以及卡诺图的最小合并规律。

ManagerUser的博客 4万+

编程助手:CLAUDE.md 与 AGENTS.md 完全指南

AI编程助手配置文件指南 为解决AI编程助手在陌生项目中面临的运行、规范、架构等问题,本文提出两种配置文件: CLAUDE.md(根目录): 面向通用AI(如ClaudeCode) 包含项目命令、代码风格、架构说明等结构化信息 示例:启动命令:npm run dev,代码规范:TypeScript禁用any AGENTS.md(任意目录): 面向智能编码工具(如Cursor) 支持模块级配置(如微前端子应用) 示例:前端测试命令:npm test:web,API请求规范 与传统README.md的区别: 人

分享AI、区块链技术及应用,未来已来 1252

数字逻辑:卡诺图详解

开关函数最简形式: 平时的逻辑代数化简有技巧性,而且也不知道是不是最简,我们今天来学习如何处理。 在最简表达式中,逻辑门数量最少,输入最少。最简表达式不一定唯一,但大家的门,输入肯定一样多。 想要化简,可以用卡诺图。(3,4变量时非常好用) 有点看不懂?详解如下: 2^n个小格,是因为n个元素就有2^n个最小项。 横,竖轴上的坐标要是格雷码,这样只要格子相邻,对应的最小项就是相邻的(只有一位不同)在逻辑上相邻。(这一点表现得还不够明显,看下图): 横轴,竖轴是格雷码更加明显了。 ..

LI_XIAO_XING的博客 8万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

卡诺图化简

为了保证图中几何位置相邻的最小项在逻辑上也具有相邻性,这些数码不.能按自然二进制数从小到大地顺序排列,而必须按图中的方式排列,以确保相邻的两个最小项仅有一个变量是不同的。③有些为“1”的小方块可以被圈一-次以上,但在新圈定的圈内至少要包含一-个在原有圈内从未被圈过的“1”的方块,所以画完圈后要检查是否满足要求;②4个小方块组成一个大方块,或组成同一行/列,或组成两行/列的两端,或处于四角,可以合并,消去2个变量。②画卡诺圈,将相邻的“1’’方格按2"圈为一组,真到所有的“1”被圈完;①画出函数的卡诺图;

qq_45766606的博客 2万+

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

看完这篇还不会化简卡诺图?你来打我

最通俗易懂的的卡诺图化简教程 首先我们来介绍一下什么是卡诺图: 卡诺图是逻辑函数的一种图形表示。一个逻辑函数的卡诺图就是将此函数的最小项表达式中的各最小项相应地填入一个方格图内,此方格图称为卡诺图。 卡诺图的构造特点使卡诺图具有一个重要性质:可以从图形上直观地找出相邻最小项。两个相邻最小项可以合并为一个与项并消去一个变量。(摘自百度百科) 卡诺图法与代数法都可以作为化简逻辑函数的依据,...

weixin_44754436的博客 4万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

数字电路:卡诺图

假设现在有一个逻辑电路,我们知道所有输入对应的输出,该如何找到这个系统的最简逻辑表达式呢? 卡诺图就是方法之一,其要点在于,通过一张图表现出所有输入与输出之间的关系,然后通过画圈的方式找到最简的SOP(sum of product),其中,相邻的项可以被一个圈包裹,但是圈中项的数量必须是2的指数倍(1,2,4,8…),每个圈中至少要有一个未被其它圈包裹的项,最后,圈最少的画法就能对应最简SOP 1...

无机肥料的博客 1万+

一文搞懂卡诺图

卡诺图1.1 卡诺图的结构1.2 最小项表达式1.2.1 介绍1.2.2 特点1.3 相邻组合1.3.1 几何相邻1.3.2 逻辑相邻1.4 卡诺图的表示1.5 卡诺图简化1.5.1 规则1.5.2 步骤1.5.3 无关项简化 1.1 卡诺图的结构 卡诺图可以表示和化简逻辑函数,一个逻辑函数的卡诺图,就是将此函数的最小项表达式中的各最小项填入相应的特定方格图内,这样的方格图就是卡诺图。 1.2 最小项表达式 1.2.1 介绍 一个逻辑函数,如果有n个变量,则有2^n个最小项,最小项为所有所有变量的积,也就是

浅谈 1万+

逻辑代数基础(二)(卡诺图)

逻辑代数基础(二)(卡诺图)

qwertf123的博客 1万+

卡诺图在程序中的应用

目录 二灯游戏 三灯游戏 卡诺图的相关知识可以参考此处:https://blog.youkuaiyun.com/hahasusu/article/details/88244155 二灯游戏 一个游戏机有两个灯,一黄一绿,它们忽闪忽灭,你必须在出现以下情况的时候迅速按下游戏机: 绿灯灭,黄灯亮 绿灯、黄灯都灭 绿灯、黄灯都亮 解题思路: 1、首先定义两个基本的命题 命题A:绿灯亮 命题B:...

hahasusu的专栏 2181
上一篇: hdu 4412 Sky Soldiers(区间DP)
下一篇: 网络流之--最小点权覆盖和最大点权独立集
SprintfWater
博客等级 码龄15年 242粉丝 139原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值