📜  门| GATE 2017 MOCK II |第 34 题(1)

📅  最后修改于: 2023-12-03 15:12:34.956000             🧑  作者: Mango

门| GATE 2017 MOCK II |第 34 题

本题是2017年GATE考试MOCK-2中的第34题,是一道关于门电路的算法题。

题目描述

给定一个由N个门(AND,OR和NOT)组成的门电路,以及每个门的输入电压和输出电压。假设每个门的输入电压是1或0,输出电压也是1或0。现在,要求你判断是否存在一种输入方式,可以使整个门电路输出为1。

输入格式

第一行包含一个整数T,表示测试用例的数量。接下来T组测试数据。每组测试数据的第一行包含一个整数N,表示门的数量。接下来一行包含N个整数,其中第 i 个整数表示第 i 个门的输入电压。

对于每个门,其输入电压的数量与类型与其类型相对应。如AND门具有两个输入,OR门具有两个输入,NOT门具有一个输入。输入电压为1或0,以空格分隔。

接下来一行包含N个整数,其中第 i 个整数表示第 i 个门的输出电压(输出电压为1或0)。

接下来N行,每行包含若干个整数。如果第 i 行的第 j 个整数不为0,表示第 i 个门的第 j 个输入是第 j 个门的输出。

输出格式

对于每个测试用例,输出一行包含一个整数,如果存在一种输入方式使整个门电路的输出为1,则输出“1”,否则输出“0”。

输入样例
2
4
0 0 1 1
1 1 0 0
0 0 0 1
1 1 0 0
0 0 0 1
0 0 0 0
0 0 1 1
0 0 1 1
5
1 0 0 0 0
0 1 1 1 1
0 0 0 1 1
1 1 0 0 0
0 0 1 1 0
0 0 0 0 0
0 0 0 0 1
0 1 0 0 0
0 1 0 0 1
0 0 0 0 0
输出样例
1
0
解题思路

本题需要使用递归算法来遍历所有可能的输入情况。具体做法是,依次将N个门的输入电压赋值为0或1,然后递归调用自己,直到达到最后一个门。

递归完成后,再逐个判断每个门的输出是否符合要求,如果满足至少有一个门输出为1,则整个门电路输出为1,否则输出为0。

具体实现见下面的示例代码。

def find_solution(inputs, outputs, connections, gate_values, current_gate_index):
    # 递归终止条件,如果最后一个门处理完毕,则返回True 或 False
    if current_gate_index == len(gate_values):
        for output in outputs:
            if output != 1:
                return False
        return True
    # 对于当前门,依次将其输入电压赋值为0或1,然后递归调用自身
    for i in range(len(connections[current_gate_index])):
        input_gate_index = connections[current_gate_index][i]
        gate_values[current_gate_index][i] = inputs[input_gate_index - 1]
    inputs_for_next_gate = [gate_values[current_gate_index][i] for i in range(len(gate_values[current_gate_index]))]
    if gate_types[current_gate_index] == 'AND':
        output = 1
        for input_voltage in inputs_for_next_gate:
            output = output & input_voltage
    elif gate_types[current_gate_index] == 'OR':
        output = 0
        for input_voltage in inputs_for_next_gate:
            output = output | input_voltage
    elif gate_types[current_gate_index] == 'NOT':
        output = 1 - inputs_for_next_gate[0]
    gate_values[current_gate_index][-1] = output
    # 递归调用自身处理下一个门
    if find_solution(inputs, outputs, connections, gate_values, current_gate_index + 1):
        return True
    # 回溯前,需要将当前门的输出电压清零
    gate_values[current_gate_index][-1] = 0
    # 如果上一个门不符合要求,将当前门设为1再进行递归调用
    for i in range(len(connections[current_gate_index])):
        input_gate_index = connections[current_gate_index][i]
        gate_values[current_gate_index][i] = 1 - inputs[input_gate_index - 1]
    inputs_for_next_gate = [gate_values[current_gate_index][i] for i in range(len(gate_values[current_gate_index]))]
    if gate_types[current_gate_index] == 'AND':
        output = 1
        for input_voltage in inputs_for_next_gate:
            output = output & input_voltage
    elif gate_types[current_gate_index] == 'OR':
        output = 0
        for input_voltage in inputs_for_next_gate:
            output = output | input_voltage
    elif gate_types[current_gate_index] == 'NOT':
        output = 1 - inputs_for_next_gate[0]
    gate_values[current_gate_index][-1] = output
    result = find_solution(inputs, outputs, connections, gate_values, current_gate_index + 1)
    # 回溯前,需要将当前门的输出电压清零
    gate_values[current_gate_index][-1] = 0
    return result


# 读入测试数据
t = int(input())
for i in range(t):
    n = int(input())
    inputs = list(map(int, input().split()))
    outputs = list(map(int, input().split()))
    gate_types = []
    for j in range(n):
        line = input().split()
        gate_type = line.pop(0)
        gate_types.append(gate_type)
    connections = []
    for j in range(n):
        line = list(map(int, input().split()))
        connections.append([x for x in range(1, n+1) if line[x-1]])
    gate_values = [[0] * (len(connections[x]) + 1) for x in range(n)]
    # 检查是否存在一种输入方式使整个门电路的输出为1
    if find_solution(inputs, outputs, connections, gate_values, 0):
        print(1)
    else:
        print(0)

此算法的时间复杂度是指数级的,可能无法处理超过10个门电路的测试数据。