202009-3 点亮数字人生
一. 原理
这道题本身是一个图的题。可以将每个逻辑门抽象为图的节点,输入输出抽象为有向边。
题目需要根据输入计算每个逻辑门的输出,并且要求判断是否有环。
那么正常这就是一个标准DAG图(有向无环图)。对DAG图可进行拓扑排序操作,在进行排序后逐一输出每个门的output。
若经过拓扑排序后,还有部分节点没有被排序,则说明该图有环。
二. 代码
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
#include <stack>
using namespace std;
struct node{
int id;
int type;
//input 0
//NOT 1 非
//AND 2 与
//OR 3 或
//XOR 4 异或
//NAND 5 与非(先全部与后取非)
//NOR 6
vector<node*> childs;
vector<node*> fathers;
node(){
type = 0;
}
};
struct mechine{
vector<node*> inputs;
vector<node*> doors;
vector<node*> sort_doors;
vector<bool> output;
mechine(int m,int n){
//m input
//n doors
for(int i = 0; i < m;i++){
inputs.push_back(new node());
}
for(int j = 0; j < n;j++){
doors.push_back(new node());
}
}
void add_doors(int p,int type){
//p doors's number
//type door's type
doors[p]->id = p;
doors[p]->type = type;
}
void add_eage(int p,int input_num,bool input){
//p doors's number
//input_num input's num
//input or output by door
if(input){
inputs[input_num]->childs.push_back(doors[p]);
doors[p]->fathers.push_back(inputs[input_num]);
}else{
doors[input_num]->childs.push_back(doors[p]);
doors[p]->fathers.push_back(doors[input_num]);
}
}
bool topology(){
vector<int> curr_count(doors.size(),0);
queue<node*> myqueue;
//init
for(int i = 0; i < inputs.size(); i++){
inputs[i]->id = i;
myqueue.push(inputs[i]);
}
while(!myqueue.empty()){
node* curr = myqueue.front();
myqueue.pop();
if(curr->type != 0){
sort_doors.push_back(curr);
}
for(int i = 0; i < curr->childs.size();i++){
curr_count[curr->childs[i]->id]++;
if(curr_count[curr->childs[i]->id] == curr->childs[i]->fathers.size()){
myqueue.push(curr->childs[i]);
}
}
}
return sort_doors.size() == doors.size();
}
bool addflag(bool flag,bool add,int type){
switch(type){
case 1:
//不可能为这种情况
break;
case 2:
flag = flag && add;
break;
case 3:
flag = flag || add;
break;
case 4:
flag = (flag && !add) || (!flag && add);
break;
case 5:
flag = !(flag && add);
break;
case 6:
flag = !(flag || add);
break;
default:
break;
}
return flag;
}
void cal(vector<bool>& input_value){
output.clear();
output.resize(doors.size());
//init
for(int i = 0; i < sort_doors.size(); i++){
bool flag ;
node* curr = sort_doors[i];
for(int j = 0; j < curr->fathers.size();j++){
node* curr_father = curr->fathers[j];
if(curr_father->type == 0){
if(j == 0){
if(curr->type == 1){
flag = (bool)(!input_value[curr_father->id]);
}else{
flag = (bool)input_value[curr_father->id];
}
}else{
// printf("flag:%d %d %d\n",flag,(bool)input_value[curr_father->id],curr->type);
flag = addflag(flag,(bool)input_value[curr_father->id],curr->type);
// printf("flag:%d\n",flag);
}
}else{
if(j == 0){
if(curr->type == 1){
flag = (!output[curr_father->id]);
}else{
flag = output[curr_father->id];
}
}else{
flag = addflag(flag,output[curr_father->id],curr->type);
}
}
}
output[curr->id] = flag;
// printf("output:%d %d %d\n",curr->id,curr->type,(int)output[curr->id]);
}
}
};
int main(){
int q;
scanf("%d",&q);
for(int i = 0; i < q; i++){
int M,n;
scanf("%d %d",&M,&n);
mechine m(M,n);
char str[6];
for(int j = 0; j < n; j++){
int type;
string func;
int input_num;
scanf("%s %d",str,&input_num);
func = str;
if(func == "NOT")
type = 1;
else if(func == "AND")
type = 2;
else if(func == "OR")
type = 3;
else if(func == "XOR")
type = 4;
else if(func == "NAND")
type = 5;
else if(func == "NOR")
type = 6;
else
type = 0;
//add door
m.add_doors(j,type);
//add eages
for(int k = 0 ; k < input_num; k++){
char temp;
int p;
scanf("%c",&temp);
scanf("%c%d",&temp,&p);
if(temp == 'I'){
m.add_eage(j,p-1,true);
}else if(temp == 'O'){
m.add_eage(j,p-1,false);
}else{
}
}
}
int s;
scanf("%d",&s);
vector<vector<bool> > input_value_group(s);
for(int j = 0; j < s; j++){
for(int k = 0; k < M; k++){
bool temp;
scanf("%d",&temp);
// printf("%d\n",temp);
input_value_group[j].push_back(temp);
}
}
bool loop = !m.topology();
//cal
for(int j = 0; j < s; j++){
int num_re;
scanf("%d",&num_re);
if(!loop){
m.cal(input_value_group[j]);
}
for(int k = 0; k < num_re; k++){
int want_p;
scanf("%d",&want_p);
if(!loop){
printf("%d ",(int)m.output[want_p-1]);
}
}
if(!loop){
printf("\n");
}
}
if(loop){
printf("LOOP\n");
}
}
return 0;
}