第 20 次 CSP认证 202009-3 点亮数字人生--个人代码实现(100分代码)

1. 题目详情

https://blog.csdn.net/weixin_45884316/article/details/108572358

2. 思路:

一句话:拓扑排序,在每次出队时计算出队的器件的输出。
此题复杂之处在于题目各种数据的存储方式,以本人的设置为例:

//相关数组大小
const int N = 510 , K = 5 , M = N * N / 2 , SM = 1e4;
//<char , int>二元组
typedef pair<char , int> PCI;
//器件结构体数组
struct func
{
	char fun[K]; //器件功能
	PCI port[K];//端口,char表示I/O,int表示I/O的编号
	int out;		  //本器件的输出
	int p_num; //端口数目
}funcs[N];

int input[SM][N * K];//多轮输入
int q[N];				   //询问
int h[N] , e[M] , ne[M] , idx;//邻接表
int d[N];							 //结点(器件)入度
int bkd[N];						//入度数组备份
int in_num , func_num;	//输入、器件总数目

3. 代码实现

#include <iostream>
#include <cstring>
#include <queue>
#include <stdlib.h>
#define x first
#define y second

using namespace std;

const int N = 510 , K = 5 , M = N * N / 2 , SM = 1e4;

typedef pair<char , int> PCI;

struct func
{
	char fun[K]; 
	PCI port[K];
	int out;
	int p_num;	
}funcs[N];

int input[SM][N * K];
int q[N];
int h[N] , e[M] , ne[M] , idx;
int d[N];
int bkd[N];
int in_num , func_num;

void add(int a , int b)
{
	e[idx] = b , ne[idx] = h[a] , h[a] = idx++;
	
}

bool topsort(int s)
{
	queue<int> qu;
	int a[N];
	int cnt = 0;
	
	for(int i = 1; i <= func_num; ++i)
		if(!d[i])	qu.push(i);
	
	while(qu.size())
	{
		int t = qu.front();
		a[++cnt] = t;
	//	printf("%d\n" , t);
		qu.pop();
		
		int & out = funcs[t].out;
		int  & pnum =  funcs[t].p_num;
		
		if(funcs[t].port[1].x == 'O')	out = funcs[ funcs[t].port[1].y ].out;
		else	out = input[s][funcs[t].port[1].y];
		
		if(!strcmp(funcs[t].fun , "AND"))
		{
			
			for(int i = 2; i <= pnum; ++i)
			{
				if(funcs[t].port[i].x == 'O')	out &= funcs[ funcs[t].port[i].y ].out;
				else	out &= input[s][funcs[t].port[i].y];
			}
		}
		else if(!strcmp(funcs[t].fun , "OR"))
			{
				
				for(int i = 2; i <= funcs[t].p_num; ++i)
				{
					if(funcs[t].port[i].x == 'O')	out |= funcs[ funcs[t].port[i].y ].out;
					else	out |= input[s][funcs[t].port[i].y];
				}
			}
		else if	(!strcmp(funcs[t].fun , "XOR"))
			{
					
				for(int i = 2; i <= funcs[t].p_num; ++i)
				{
					if(funcs[t].port[i].x == 'O')	out ^= funcs[ funcs[t].port[i].y ].out;
					else	out ^= input[s][funcs[t].port[i].y];
				}
			}
		else if	(!strcmp(funcs[t].fun , "NAND"))
			{
				
				for(int i = 2; i <= funcs[t].p_num; ++i)
				{
					if(funcs[t].port[i].x == 'O')	out &= funcs[ funcs[t].port[i].y ].out;
					else	out &= input[s][funcs[t].port[i].y];
				}
				out ^= 1;
			}
		else if	(!strcmp(funcs[t].fun , "NOR"))
			{
				for(int i = 2; i <= funcs[t].p_num; ++i)
				{
					if(funcs[t].port[i].x == 'O')	out |= funcs[ funcs[t].port[i].y ].out;
					else	out |= input[s][funcs[t].port[i].y];
				}
				out ^= 1;
			}
		else out ^= 1;
		
		for(int i = h[t]; ~i; i = ne[i])
		{
			int j = e[i];
			if(--d[j] == 0)
			{
				qu.push(j);
			}		
		}		
	}	
	
	
	if(cnt == func_num && cnt)	return true;
	else return false;
//	for(int i = 1; i <= func_num; ++i)	
//		if(d[i])	return false;
//	return true;
}


int main()
{
//	freopen("in.txt" , "r" , stdin);
//	freopen("out.txt" , "w" , stdout);
	
	int Q;
	scanf("%d" , &Q);
	while(Q--)
	{
		scanf("%d%d" , &in_num, &func_num);
	//	getchar();
		
		idx = 0;
		memset(h , -1 , sizeof(h));
		memset(e , 0 , sizeof(e));
		memset(ne , 0 , sizeof(ne));
		memset(d , 0 , sizeof(d));
		memset(funcs , 0 , sizeof(funcs));
		memset(input , 0 , sizeof(input));
		for(int i = 1; i <= func_num; ++i)
		{
			scanf("%s" , funcs[i].fun);
		//	printf("%s\n" , funcs[i].fun);
			scanf("%d" , &funcs[i].p_num);
		//	getchar();
			for(int j = 1; j <= funcs[i].p_num; ++j)
			{
				char tp[10];
				scanf("%s" , tp);
				int t = atoi(tp + 1);
				funcs[i].port[j].x = tp[0];
				funcs[i].port[j].y = t;
				if(tp[0] == 'O')
				{
					add(t , i);
					++d[i];
				}
			//	printf("%c%d\n" , funcs[i].port[j].x ,funcs[i].port[j].y);
			}
		}
		memcpy(bkd , d , sizeof(d));
	//	for(int i = 1; i <= func_num; ++i)	printf("%d ", d[i]);
		
		int S;
		scanf("%d" , &S);
		for(int i = 1; i <= S; ++i)
		{
			for(int j = 1; j <= in_num; ++j)
			{
				scanf("%d" , &input[i][j]);
			//	printf("%d\n" , input[i][j]);
			}
		}
				
		bool has_loop = false; 
		//solution
		for(int i = 1; i <= S; ++i)
		{
			memset(q , 0 , sizeof(q));
		
			int s;
			scanf("%d" , &s);
			for(int j = 1; j <= s; ++j)
				scanf("%d" , &q[j]);
			if(!topsort(i))	
			{
				has_loop = true;
				//break;
			}
			else
			{
				for(int j = 1; j < s; ++j)
					printf("%d ", funcs[q[j]].out);
				printf("%d", funcs[q[s]].out);
				puts("");
			}
//			for(int j = 1; j <= func_num; ++j)
//				printf("%d " , funcs[j].out); 
			memcpy(d , bkd , sizeof(d));
			for(int i = 1; i <= func_num; ++i)	funcs[i].out = 0;
		}				
		if(has_loop)	puts("LOOP");
				
		//reset	
	}
	
//	fclose(stdin);
//	fclose(stdout);

	return 0;
}

特别鸣谢

https://blog.csdn.net/u011902923/article/details/108890765?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242

这篇博客的大佬指出了输入读取不完全的问题,特此表达感谢!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值