【CSP】点亮数字人生(202009)

【CSP】点亮数字人生(202009)

1. 分析

在这里插入图片描述

正确的解题思路:

  • 拓扑排序(Topological Sort)
    使用拓扑排序确定处理电路门的顺序。
  • 大模拟
    使用与(&)、或(|)、非(!)、异或(^)等操作模拟电路门,由输入信号得出输出信号。
  • 作用域
    这道题的输入格式很奇怪。先输入所有问题的电路门的结构,再输入所有问题的电路门的输入,最后输入所有的问题要输出的电路门编号。而不是一个个问题输入。
    多次处理同一个问题时,巧妙地利用作用域(例如,将整个问题抽象成函数,将所有所需的变量封装在一个函数内),可以避免需要清理上个问题留下的数据的问题。
  • 变量命名与注释
    大模拟的题往往涉及很多相关的变量,变量命名应该尽量规范且贴合题意。退一步来说,最起码也得在变量定义处写好注释。

2. 代码

  • 当前这个代码得分40。初始化能运行的部件,不断更新可以运行的部件,运行到最后如果发现还有部件未运行或者不能运行,则说明有环路。
  • 满分ac的在这儿:点亮数字人生(原创代码100分)
#include"stdio.h"
#include"iostream"
#include"string"
using namespace std;
struct IN{
	int in;
	int num;
	int sp;
};
struct F{
	int fg;	//func
	int k;	//输入个数 
	IN in[5];
	int out;
	int ready;
};
int Q;
int M,N;
int  S;
int Not(int a){
	return 1-a;
}
int  And(F f){
	int t=f.in[0].sp;
	int k=f.k;
	for(int i=1;i<k;i++){
		t=t&f.in[i].sp;
	}
	return t;
}
int  Or(F f){
	int t=f.in[0].sp;
	int k=f.k;
	for(int i=1;i<k;i++){
		t=t|f.in[i].sp;
	}
	return t;
}
int  Xor(F f){
	int t=f.in[0].sp;
	int k=f.k;
	for(int i=1;i<k;i++){
		if(t!=f.in[i].sp){
			t=1;
		}
		else{
			t=0;
		}
	}
	return t;
}
int  Nand(F f){
	return 1-And(f);
}
int  Nor(F f){
	return 1-Or(f);
}
int find(char s[5]){
	if(s[0]=='A'){
		return 2;
	}
	else{
		if(s[0]=='O'){
			return 3;
		}
		else{
			if(s[0]=='X'){
				return 4;
			}
			else{
				if(s[1]=='A'){
					return 5;
				}
				else{
					if(s[2]=='T'){
						return 1;
					}
					else return 6;
				}
			}
		}
	}
	return 0;
}
int getnum(char s[10]){
	int i=1,num=0;
	while(s[i]!=0){
		num=num*10+s[i]-'0';
		i++;
	}
	return num;
}
int work(F *f){
	int fla[501];
	for(int i=1;i<=N;i++){
		fla[i]=0;
	}
	int flag=1,count2,count1=0,fff=0;
	while(flag){
		count2=count1;
		count1=0;
		flag=0;
		for(int i=1;i<=N;i++){
			if(f[i].ready==f[i].k&&fla[i]==0){
				int fg=f[i].fg;
				switch (fg){
					case 1:f[i].out=Not(f[i].in[0].sp);break;
					case 2:f[i].out=And(f[i]);break;
					case 3:f[i].out=Or(f[i]);break;
					case 4:f[i].out=Xor(f[i]);break;
					case 5:f[i].out=Nand(f[i]);break;
					case 6:f[i].out=Nor(f[i]);break;
					default:break;
				}
				fla[i]=1;
				for(int ii=1;ii<=N;ii++){
					for(int iii=0;iii<f[ii].k;iii++){
						if(f[ii].in[iii].in==0&&f[ii].in[iii].num==i){
							f[ii].in[iii].sp=f[i].out;
							f[ii].ready++;
						}
					}
				} 
			}
		}
		for(int i=1;i<=N;i++){
			if(fla[i]==0){
				flag=1;
				count1++;
			} 
		} 
		if(count2==count1&&count1!=0){
			fff=1;
			flag=0;
		}
	} 
	if(fff){
		return 1;
	}
	return 0;
}
int main(){
	int in[500][100];
	int out[500][100];
	int si[100];
	scanf("%d",&Q);
	for(int i=0;i<Q;i++){
		F f[501];
		scanf("%d%d",&M,&N);
		for(int j=1;j<=N;j++){
			char s[5];
			int k;
			scanf("%s%d",s,&k);
			f[j].k=k;
			f[j].fg=find(s);
			for(int l=0;l<k;l++){
				char L[10];
				scanf("%s",L);
				if(L[0]=='I'){
					f[j].in[l].in=1;
				}
				else{
					f[j].in[l].in=0;
				}
				f[j].in[l].num=getnum(L);
			}
		}
		scanf("%d",&S);
		for(int i1=0;i1<S;i1++){
			for(int j=1;j<=M;j++){
				scanf("%d",&in[i1][j]);
			}
		}
		for(int i1=0;i1<S;i1++){
			scanf("%d",&si[i1]);
			for(int j=0;j<si[i1];j++){
				scanf("%d",&out[i1][j]);
			}
		}
		int w=0;
		for(int i=0;i<S;i++){
			for(int ii=1;ii<=N;ii++){
				f[ii].ready=0;
			}
			for(int j=1;j<=M;j++){
				for(int ii=1;ii<=N;ii++){
					for(int jj=0;jj<f[ii].k;jj++){
						if(f[ii].in[jj].in==1&&f[ii].in[jj].num==j){
							f[ii].in[jj].sp=in[i][j];
							f[ii].ready++;
						}
					}
				}
			}
			w=work(f);
			if(w==1){
				printf("LOOP\n");
				break;
			} 
			else{
				for(int j=0;j<si[i];j++){
					printf("%d ",f[out[i][j]].out);
				}
				printf("\n");
			}
		} 
	}
	return 0;
}


/*
2
2 6
NOR 2 O4 I2
AND 2 O4 O6
XOR 2 O5 O1
NOT 1 O6
NAND 2 O2 O2
AND 2 I1 O3
2
0 0
1 0
3 2 3 4
6 1 2 3 4 5 6
3 5
XOR 2 I1 I2
XOR 2 O1 I3
AND 2 O1 I3
AND 2 I1 I2
OR 2 O3 O4
4
0 1 1
1 0 1
1 1 1
0 0 0
2 5 2
2 5 2
2 5 2
2 5 2

*/




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋冬无暖阳°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值