CCFCSP认证 2020-09C点亮数字人生

【!!最近写了好多C题,打算先放代码供大家参考,之后再补充题解!!】

题目大意

考点

思路

易错点

收获

满分代码

//0.循环q个问题(初始化)
//1.构建电路(toposort),判环,注意编号转换
//2.对每个电路,读入s行个输入,构建k个bitset
//3.遍历结果
//4.对每个回答i的每个器件,找到目标器件对应维度i的值

#include <bits/stdc++.h>

using namespace std;

const int N=1e3+10,S=1e4+10;
#define fi first
#define se second
#define pb push_back

typedef pair<int,int> PII;
typedef struct Node{
    int no,typ;//0-4
}node;
int n,m,q,s,to_ori_no[N],deg[N],st[N],idx;//deg表示入度
vector<int> h[N],revh[N];//h为有向图,点指向所需要的值,revh为返图
node a[N];


void ini(){
    for(int i=1;i<=n;i++)deg[i]=0;
    for(int i=1;i<=n;i++)h[i].clear();//chongzhi
    for(int i=1;i<=n;i++)revh[i].clear();//chongzhi
    for(int i=1;i<=n;i++)to_ori_no[i]=0;
    for(int i=1;i<=n;i++)st[i]=0;
    idx=0;
}


int get_num(string s){
    int res=0;
    for(int i=0;i<s.length();i++){
        res*=10;
        res+=s[i]-'0';
    }
    return res;
}

int trans(string op){
    if(op=="NOT")return 0;
    else if(op=="AND")return 1;
    else if(op=="OR")return 2;
    else if(op=="XOR")return 3;
    else if(op=="NAND")return 4;
    else if(op=="NOR")return 5;
}


int main(){
    cin>>q;
    while(q--){
        cin>>m>>n;
        ini();
        node tmp[N];
        bool curr_flag;

        //构建电路
        for(int i=1;i<=n;i++){
            string op;
            int k;
            cin>>op;
            tmp[i].no=i;
            tmp[i].typ=trans(op);
            cin>>k;
            //统计入度(即其所依赖的元件)
            for(int j=0;j<k;j++){
                cin>>op;
                int x=get_num(op.substr(1));//??
                if(op[0]=='I'){//输入信号
                    h[i].pb(x+n);//m个输入信号从n+1开始编号
                }
                else{//元件
                    deg[i]++;
                    h[i].pb(x);
                    revh[x].pb(i);
                }
            }
        }



        //ttoposort
        queue<int>q;
        for(int i=1;i<=n;i++){
            if(deg[i]==0 && st[i]==0){
                q.push(i);
                to_ori_no[i]=++idx;
                a[idx]=tmp[i];

            }
        }


        while(!q.empty()){
            int cur=q.front(); q.pop();
            for(int j:revh[cur]){
                    deg[j]--;
                    if(deg[j]==0){
                        q.push(j);
                        to_ori_no[j]=++idx;
                        a[idx]=tmp[j];
                    }
            }
        }

        //for(int i=1;i<=n;i++)cout<<a[i].no<<"!";
        //cout<<endl;
        //判环
        curr_flag=(idx==n);//0表示有环

        //读入s个输入
        cin>>s;
        vector<bitset<S>> input(m+5);
        for(int i=0;i<s;i++){
            for(int j=1;j<=m;j++){
                int x;
                cin>>x;
                if(x)input[j].set(i);

            }
        }

        //for(int i=1;i<=m;i++)cout<<input[i]<<"@";

        //遍历结果
        vector<bitset<S>> ans(n+5);
        //易错,转换
        for(int i=1;i<=n;i++){
            bitset<S> res;
            int cnt=0;
            int opr=a[i].typ;
            for(int j:h[a[i].no]){
                //cout<<j<<"!";

                bitset<S>op;
                if(j>n)op=input[j-n];
                else op=ans[to_ori_no[j]];//已经算过了
                if(opr==0){
                    op.flip();
                    res=op;
                }
                else if(opr==1 || opr==4){
                    if(!cnt)res=op;
                    else res&=op;
                }
                else if(opr==2 || opr==5){
                    if(!cnt)res=op;
                    else res|=op;
                }
                else{
                    if(!cnt)res=op;
                    else res^=op;
                }
                cnt++;

            }
            if(opr>3)res.flip();
            ans[i]=res;
            //cout<<endl;
            //cout<<ans[i][0]<<endl;
        }



        //读入s行行为描述
        for(int i=0;i<s;i++){
            int cnt;
            cin>>cnt;
            for(int j=0;j<cnt;j++){
                int x;
                cin>>x;
                if(curr_flag)cout<<ans[to_ori_no[x]][i]<<" ";
            }
            if(curr_flag)cout<<endl;
        }
        if(!curr_flag)cout<<"LOOP\n";


    }

    return 0;
}





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值