蓝桥杯-My bad

如题,算法不麻烦,写得有点麻烦,这题需要考虑好用什么数据结构,怎么存这么多的输入。
我用的是类,门类,一个门对应一个门对象,变量有类型、输入来源、输出、方法有计算输出,参数为输入来源的输入。
计算输出时,电路输入可直接进行计算,门输入还要先计算该门的输出,用到了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,以及不能直接用集合做参数。还有一点就是,官网给的答案有些是错的,不信可自行验证。

猜你喜欢

转载自blog.csdn.net/weixin_42419611/article/details/104932220
今日推荐