如题,算法不麻烦,写得有点麻烦,这题需要考虑好用什么数据结构,怎么存这么多的输入。
我用的是类,门类,一个门对应一个门对象,变量有类型、输入来源、输出、方法有计算输出,参数为输入来源的输入。
计算输出时,电路输入可直接进行计算,门输入还要先计算该门的输出,用到了DFS;最后打印错误信息时,需要考虑清楚错误产生的原因,一个门可能有2种错误,即全反+全0/全1,若存在多个错误信息那就意味着无法诊断:
#include<bits/stdc++.h>
using namespace std;
class gate {
public:
gate(void) {}
char type; //门的类型
vector<string> from; //输入来源,非门只有一个输入,其他两个
bool out = 0; //输出一个
void settype(char t) {
this->type = t;
}
void setfrom(vector<string> i) {
this->from = i;
}
bool setout(vector<bool> i) {
if (type == 'n') {
this->out = !i[0];
return !i[0];
}
else if (type == 'a') {
if (i[1] == 1 && i[0] == 1) {
this->out = 1;
return 1;
}
else this->out = 0;
}
else if (type == 'o') {
if (i[1] == 1 || i[0] == 1) {
this->out = 1;
return 1;
}
else this->out = 0;
}
else if (type == 'x') {
if ((i[1] == 0 && i[0] == 1) || (i[1] == 1 && i[0] == 0)) {
this->out = 1;
return 1;
}
else this->out = 0;
}
return 0;
}
};
vector <gate> Gate;
int n, g, u; //输入数、门数、输出数
vector<int> counts;
void dfs(bool in[10], int i) //参数1为原始电路输入,参数2为门编号
{
if (counts.size() == g) //遍历了所有门
return;
//若已遍历则退出
for (int j = 0; j < counts.size(); j++)
{
if (counts[j] == i)
return;
}
counts.resize(counts.size() + 1);
counts[counts.size() - 1] = i;
if (Gate[i].from.size() == 1) //非门,一个输入来源
{
if (Gate[i].from[0].at(0) == 'i') //如果为电路输入,则找到该输入对应的编号直接计算
Gate[i].setout({ in[Gate[i].from[0].at(1) - '1'] });
else //如果是门输入,则要先计算前门的输出
{
dfs(in, Gate[i].from[0].at(1) - '1');
Gate[i].setout({ Gate[Gate[i].from[0].at(1) - '1'].out }); //前门输出计算完毕,那么setout的参数就为前门的输出
}
return;
}
else //其他三门
{
bool a = 0, b = 0;
if (Gate[i].from[0].at(0) == 'i' && Gate[i].from[1].at(0) == 'i') //如果两个输入都为电路输入
{
a = in[Gate[i].from[0].at(1) - '1']; b = in[Gate[i].from[1].at(1) - '1'];
}
else if (Gate[i].from[0].at(0) == 'g' && Gate[i].from[1].at(0) == 'i')//如果第一个输入为门输入,则要先计算前门的输出
{
dfs(in, Gate[i].from[0].at(1) - '1');
a = Gate[Gate[i].from[0].at(1) - '1'].out;
b = in[Gate[i].from[1].at(1) - '1'];
}
else if (Gate[i].from[1].at(0) == 'g'&& Gate[i].from[0].at(0) == 'i')//如果第二个输入为门输入
{
dfs(in, Gate[i].from[1].at(1) - '1');
a = in[Gate[i].from[0].at(1) - '1'];
b = Gate[Gate[i].from[1].at(1) - '1'].out;
}
else //两个都为门输入
{
dfs(in, Gate[i].from[1].at(1) - '1');
dfs(in, Gate[i].from[0].at(1) - '1');
a = Gate[Gate[i].from[0].at(1) - '1'].out;
b = Gate[Gate[i].from[1].at(1) - '1'].out;
}
//两个输入确定后,设置该门输出
Gate[i].setout({ a,b });
return;
}
}
int main()
{
int turn = 1;
while (cin >> n >> g >> u && (n != 0 || g != 0 || u != 0)) {
//输入门的信息
Gate.resize(g);
vector<string> from;
char type;
for (int i = 0; i < g; i++)
{
cin >> type;
if (type == 'n')
{
from.resize(1);
cin >> from[0];
}
else {
from.resize(2);
cin >> from[0] >> from[1];
}
Gate[i].settype(type);
Gate[i].setfrom(from);
}
vector<int> index(u); //各个输出对应的门编号
for (int i = 0; i < u; i++)
cin >> index[i];
int b; cin >> b;
bool in[10][10]; //原始输入
bool out[10][20]; //实际输出,即题目给出的输出
bool out_ture[10][20]; //理论输出,即根据输入计算而来的输出
for (int i = 0; i < b; i++)
{
for (int j = 0; j < n; j++)
cin >> in[i][j];
for (int j = 0; j < u; j++)
cin >> out[i][j];
}
//根据电路输入in[][],计算理论输出
for (int time = 0; time < b; time++) //b次实验
{
//先计算所有门的输出
counts.resize(0);
for (int i = 0; i < g; i++)
dfs(in[time], i);
for (int i = 0; i < u; i++)
out_ture[time][i] = Gate[index.at(i) - 1].out;
/*for (int j = 0; j < u; j++)
cout << Gate[index.at(j) - 1].out << " ";
cout << endl;*/
}
//理论输出计算完毕,和实际输出进行对比
vector<string> fault(0); //错误信息容器
cout << "Case " << turn << ": ";
//依次检测每个门
for (int i = 0; i < g; i++) {
int sum0 = 0, sum1 = 0, sum2 = 0;//0,1 ,反的计数器
for (int j = 0; j < b; j++)
{
if (out[j][i] != out_ture[j][i])
sum2++;
if (out[j][i] == 0)
sum0++;
if (out[j][i] == 1)
sum1++;
}
if (sum2 == b) //每次都相反
{
fault.resize(fault.size() + 1);
fault[fault.size() - 1] = "Gate " + to_string(index.at(i)) + " is failing; output inverted";
}
if (sum2 > 0 && sum0 == b) //每次都为0且有错
{
fault.resize(fault.size() + 1);
fault[fault.size() - 1] = "Gate " + to_string(index.at(i)) + " is failing; output stuck at 0";
}
if (sum2 > 0 && sum1 == b)//每次都为1且有错
{
fault.resize(fault.size() + 1);
fault[fault.size() - 1] = "Gate " + to_string(index.at(i)) + " is failing; output stuck at 1";
}
}
//没有错误信息
if (fault.size() == 0)
cout << "No faults detected" << endl;
//一个错误信息
else if (fault.size() == 1)
cout << fault[0] << endl;
//多个错误信息
else cout << "Unable to totally classify the failure" << endl;
turn++;
}
return 0;
}
运行结果:
代码版本是C++11,官网无法运行,需要自己写一个to_string,以及不能直接用集合做参数。还有一点就是,官网给的答案有些是错的,不信可自行验证。