[二分查找] UVa1607 Gates 与非门电路 (推理)

题目

这里写图片描述

思路

1._对于输入不同的x,电路最后的输出无非只有4种情况,常数0,常数1,x,非x。

  • 常数时,直接判断x=0,x=1输出是否相同。相同的话,x对电路无影响,直接输出全0或全1即可。
  • 与x有关时,即当x取0时,电路是一种结果。x取1时,电路是另一种结果。

2._**通过x=0和x=1输出不同**,判定x所在位置。
设x=0时输出0,x=1时输出1
0 0 0 0 -> 0
1 1 1 1->1
从0000开始,依次填1,当输出变成1时,就是所求x的位置。
1 0 0 0 -> 0
1 1 0 0 -> 1
(证明)
由于初始设,必然有一个过渡态满足上述情况。并且此过渡态只有一个,也证明了x最少为1个。

代码

#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 200000 + 1000;

int n, m;   // n:输入数,m:总gate数
struct gate {       // 适当时候使用结构体,可以减少变量的分散,从而提高代码可读性
    int a, b, o;    // a,b输入,o输出
}gates[maxn];

int output(int k) {     // 返回当输入是000...111(有k个0时)的结果
    for (int i = 1; i <= m; i++) {
        int a = gates[i].a;
        int b = gates[i].b;
        int va = a<0 ? -a>k : gates[a].o;
        int vb = b<0 ? -b>k : gates[b].o;
        // c++中 ? : 结构的使用
        // 如vb的赋值,若b<0,返回-b>k,否则返回gates[b].o
        gates[i].o = !(va && vb);
        // 就是当va,va全为1的时候,为0
    }
    return gates[m].o;
}

// 返回这样的k值
// 1.output(k) = output(n) = vn
// 2.output(k-1) = output(0)
int solve(int vn) {
    int L = 1, R = n;
    while (L < R) {
        int M = L + (R - L) / 2;
        if (output(M) == vn) R = M;
        else L = M + 1;
    }
    return L;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i++)
            scanf("%d%d", &gates[i].a, &gates[i].b);
        int v0 = output(0);
        int vn = output(n);
        if (v0 == vn) {
            for (int i = 1; i <= n; i++) printf("1");
        }
        else {
            int x = solve(vn);
            for (int i = 1; i < x; i++) printf("0");
            printf("x");
            for (int i = x + 1; i <= n; i++) printf("1");
        }
        printf("\n");
    }
    return 0;
}

码农小技巧

1.适当时候使用结构体,可以减少变量的分散,从而提高代码可读性。

struct gate {       
    int a, b, o;    // a,b输入,o输出
}gates[maxn];

而非

pair<int, int> G[maxn], firstrow[maxn];
int n, m, frnum, output[maxn], input[maxn];

2.c++中 ? : 结构的使用

int vb = b<0 ? -b>k : gates[b].o;
// 如vb的赋值,若b<0,返回-b>k,否则返回gates[b].o

感受

LRJ大佬真的好强。。。写出来的代码好看到无法自拔。。
我自己写这道题的代码106行还各种巨长还TLE,LRJ大佬代码简洁无比。。
都要爱上他的代码了。。。。

猜你喜欢

转载自blog.csdn.net/icecab/article/details/80623713