CF993F The Moral Dilemma 【观察,打表】
作者:互联网
给定一个三层的逻辑电路,逻辑门有 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