点亮数字人生(思路+代码)

思路:
抽象成图的问题 定义邻接表数据结构并初始化

typedef struct Node{
    int v;//边的终点
    Node(int _v):v(_v){}//初始化列表
}node;
std::vector<node> Adj[MAXV];//邻接表

审题:
1.因为题目中包含Q个问题,所以存放数据的结构每次循环开始的时候都要进行初始化。
2.输入分为两部分,顺序读入。
3.第一部分:
(1)第一行M、N表示整个电路的输入和器件的数量,N最大是500,
(2)接下来N行(从m+1到m+n),FUNC表示逻辑功能,存放在string[510]中,然后输入k,再循环k次输入,并根据此来构造图(处理输入的字符串,然后得到该器件的编号startPoint,然后令Adj[startPoint]指向num,并计算入度为广搜作准备)。
4.第二部分:
(1)第一行S表示电路运行的次数,S最大是10000.
(2)接下来S行,每行输入m个0或1,并存放在testInput[10010]中。
(3)接下来S行,根据输出器件的个数循环,并将输出器件的编号存放到testOutput[10010]中
5.拓扑循环来判断图里是否有环。
6.计算输出结果:
这里需要注意的是,因为要计算S次,所以点权值w[510]和是否访问过该点的数组visited[510]在每次计算前都要初始化,而且计算时要用一个临时数组来存放入度值。
7.题目中涉及到的字符串和数组操作:

memset(inDegree, 0, sizeof(inDegree));
std::fill(initV, initV + MAXV, false);
for(std::vector<node>::iterator j = Adj[i].begin();j != Adj[i].end();){
	j = Adj[i].erase(j);
}
for(int i = 0;i < MAXV;i++){
	type[i].clear();
}
memcpy(tempInDegree, inDegree, (m+n)* sizeof(int));//复制的字节数

8.代码:

#include<cstdio>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<string.h>
#include<algorithm>

//#include <bits/stdc++.h>
//using namespace std;

const int MAXV = 510;

typedef struct Node{
    int v;//边的终点
    Node(int _v):v(_v){}//初始化列表
}node;
std::vector<node> Adj[MAXV];//邻接表
int w[MAXV];//边权重
//bool inq[MAXV] = {false};//是否访问过
bool initV[MAXV] = {false};//是否初始化过边
int inDegree[MAXV] = {0};//入度	
//int outDegree[MAXV] = {0};//出度(未使用)
std::string type[MAXV]; //器件类型
std::vector<int> testInput[10010];//测试输入
std::vector<int> testOutput[10010];//测试输出

//拓扑排序,判断环
bool TopologicalSort(int n, int m){
    int num = 0;
    std::queue<int> q;
    int tempInDegree[MAXV];//临时存储入度
    memcpy(tempInDegree, inDegree, (m+n)* sizeof(int));//复制的字节数
    // std::copy(std::begin(inDegree), std::end(inDegree), std::begin(tempInDegree));
    for(int i = 0;i < n + m;i++){//将所有入度为0的顶点入队
        if(tempInDegree[i] == 0){
            q.push(i);
        }
    }
    while(!q.empty()){
        int u = q.front();
        q.pop();
        //邻接表
        for(int i = 0;i < Adj[u].size();i++){
            int v = Adj[u][i].v;
            tempInDegree[v]--;
            if(tempInDegree[v] == 0){
                q.push(v);
            }
        }
        num++;
    }
    if(num == n + m) return true;
    else return false;
}
//计算值
void calculateValue(int n, int m){
    std::queue<int> q;
    int tempInDegree[MAXV];//临时存储入度
    memcpy(tempInDegree, inDegree, (m+n)* sizeof(int));//复制的字节数
    for(int i = 0;i < n + m;i++){//将所有入度为0的顶点入队
        if(tempInDegree[i] == 0){
            q.push(i);
        }
    }
    while(!q.empty()){
        int u = q.front();//起始点
        q.pop();

        //邻接表
        for(int i = 0;i < Adj[u].size();i++){
            int v = Adj[u][i].v;
            tempInDegree[v]--;

            if(initV[v] == false){//之前没有被访问过
                w[v] = w[u];//赋予初始值
                if(type[v] == "NOT"){//最多或者最少都只有一个输入
                    w[v] = (!w[v]);
                }
                initV[v] = true;
            }else{
                if(type[v] == "AND" || type[v] == "NAND"){
                    w[v] &= w[u];
                }else if(type[v] == "OR" || type[v] == "NOR"){
                    w[v] |= w[u];
                }else if(type[v] == "XOR"){
                    w[v] ^= w[u];
                }
            }
            if(tempInDegree[v] == 0){
                if(type[v] == "NAND" || type[v] == "NOR"){
                    w[v] = (!w[v]);
                }
                q.push(v);
            }
        }
    }

}

int main(){
    int q, m, n;
    scanf("%d", &q);
    while(q--){//问题个数
        //初始化
        for(int i = 0;i < MAXV;i++){
            for(std::vector<node>::iterator j = Adj[i].begin();j != Adj[i].end();){
                j = Adj[i].erase(j);
            }
        }
        //std::fill(G[0], G[0] + MAXV*MAXV, 0);
        memset(inDegree, 0, sizeof(inDegree));
        //memset(outDegree, 0, sizeof(outDegree));
//        std::fill(inq, inq + MAXV, false);
        std::fill(initV, initV + MAXV, false);
        for(int i = 0;i < MAXV;i++){
            type[i].clear();
        }
        for(int i = 0;i < 10010;i++){
            for(std::vector<int>::iterator j = testInput[i].begin();j != testInput[i].end();){
                j = testInput[i].erase(j);
            }
        }
        for(int i = 0;i < 10010;i++){
            for(std::vector<int>::iterator j = testOutput[i].begin();j != testOutput[i].end();){
                j = testOutput[i].erase(j);
            }
        }

        scanf("%d%d", &m, &n);//输入个数,器件个数
        for(int num = m;num < n + m;num++){
            std::string FUNC;//器件描述
            int k;
            std::cin>>FUNC;
            type[num] = FUNC;

            scanf("%d", &k);
            for(int i = 0;i < k;i++){
                std::string L;
                std::cin>>L;
                int startPoint = std::atoi(L.substr(1, L.length() - 1).c_str()) - 1;//计算起始点编号
                if(L[0] != 'I'){//如果是输出点,则加上输入点的偏移
                    startPoint += m;
                }
                Adj[startPoint].push_back(node(num));//构造图
                //G[startPoint][num] = 1;
                // outDegree[startPoint]++;//计算出度
                inDegree[num]++;//计算入度
            }
        }

        int s;//运算次数
        scanf("%d", &s);
        for(int i = 0;i < s;i++){//输入数据
            for(int j = 0;j < m;j++){
                int input;
                scanf("%d", &input);
                testInput[i].push_back(input);
            }
        }

        for(int i = 0;i < s;i++){//输出数据
            int OutNum;
            scanf("%d", &OutNum);
            while(OutNum--){
                int output;
                scanf("%d", &output);
                output = output + m - 1;
                testOutput[i].push_back(output);
            }
        }

        if(TopologicalSort(n, m) == false){//有环
            printf("LOOP\n");
        }else{//无环
            for(int i = 0;i < s;i++){
                memset(w, 0, sizeof(w));
                //std::fill(inq, inq + MAXV, false);
                std::fill(initV, initV + MAXV, false);
                for(int j = 0;j < testInput[i].size();j++){//给初始输入点赋值
                    w[j] = testInput[i][j];
                }
                //计算点权
                calculateValue(n, m);

                for(int j = 0; j < testOutput[i].size();j++){
                    if(j != 0) printf(" ");
                    printf("%d", w[testOutput[i][j]]);
                }
                printf("\n");

            }
        }
    }//q

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值