ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF993F The Moral Dilemma 【观察,打表】

2022-07-22 19:04:17  阅读:173  来源: 互联网

标签:return int 取反 电路 打表 CF993F vec Moral op


题目链接

给定一个三层的逻辑电路,逻辑门有 OR,AND,NOR,NAND,前两层的每个门连接前一层两个门作为输入,第三层一个 OR 门连接第二层所有门。

定义逻辑电路取反是指将 OR 与 NOR 互换、AND 与 NAND 互换,求至少去掉第二层多少个门,才能使得这个逻辑电路与其取反的真值表一致。

\(n,m,k\le 50\)。


条件相当于是说对于所有输入,原电路与取反电路的【第二层所有门都输出 \(0\)】恰有一个成立。

考虑第二层的某个门,其只涉及至多 \(4\) 个输入的 \(3\) 次运算,一个必要条件是对于所有输入,原电路与取反电路至少一个输出 \(0\)。题解告诉我们这样的情况很特殊:若原电路对全 \(0\) 的输入输出 \(0\),则对于所有输入都输出 \(0\),从而原电路与取反电路其中一个对所有输入都输出 \(0\);且若原电路不对所有输入都输出 \(0\),则对于全 \(1\) 的输入输出 \(1\)。

从而不妨设第二层的所有门在原电路对所有输入都输出 \(0\)(对取反的情况再做一遍),剩下的要求就是存在一个门在取反电路对所有输入都输出 \(1\),直接把能选的都选上就完事了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 50;
int n, m, k, ans, rs1[N], rs2[N];
char s1[10], s2[N + 5];
bool cal(int op, bool x, bool y){
	if(op == 0) return x && y;
	if(op == 1) return !(x && y);
	if(op == 2) return x || y;
	return !(x || y);
}
struct Node {
	int op, x, y;
	void read(){
		cin >> s1 >> s2;
		if(s1[0] == 'a') op = 0;
		else if(s1[1] == 'a') op = 1;
		else if(s1[0] == 'o') op = 2;
		else op = 3;
		int l = strlen(s2);
		for(x = 0;x < l;++ x) if(s2[x] == 'x')
			for(y = x + 1;y < l;++ y) if(s2[y] == 'x') return;
	}
} a[N], b[N];
int main(){
	ios::sync_with_stdio(0);
	cin >> n >> m >> k;
	for(int i = 0;i < m;++ i) a[i].read();
	for(int i = 0;i < k;++ i) b[i].read();
	for(int i = 0;i < k;++ i){
		vector<int> vec = {a[b[i].x].x, a[b[i].x].y, a[b[i].y].x, a[b[i].y].y};
		sort(vec.begin(), vec.end()); vec.resize(unique(vec.begin(), vec.end()) - vec.begin());
		int S = 0, lim = 1 << vec.size();
		auto getv = [&](int a) -> bool {
			return S >> (lower_bound(vec.begin(), vec.end(), a) - vec.begin()) & 1;
		};
		for(;S < lim;++ S){
			bool x1 = getv(a[b[i].x].x), x2 = getv(a[b[i].x].y), x3 = getv(a[b[i].y].x), x4 = getv(a[b[i].y].y);
			rs1[i] |= 1 << cal(b[i].op, cal(a[b[i].x].op, x1, x2), cal(a[b[i].y].op, x3, x4));
			rs2[i] |= 1 << cal(b[i].op ^ 1, cal(a[b[i].x].op ^ 1, x1, x2), cal(a[b[i].y].op ^ 1, x3, x4));
		}
	}
	int tot = 0; bool flg = 0;
	for(int i = 0;i < k;++ i) if(rs2[i] == 1){++ tot; flg |= rs1[i] == 2;}
	if(flg) ans = tot;
	tot = 0; flg = 0;
	for(int i = 0;i < k;++ i) if(rs1[i] == 1){++ tot; flg |= rs2[i] == 2;}
	if(flg) ans = max(ans, tot);
	printf("%d\n", ans ? k - ans : -1);
}

标签:return,int,取反,电路,打表,CF993F,vec,Moral,op
来源: https://www.cnblogs.com/AThousandMoons/p/16506822.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有