CCF CSP 202009-3 点亮数字人生

本题主要考察 有向图是否存在环路,记忆化搜索,状态压缩存储。
在这里插入图片描述

#include <bits/stdc++.h>
//#include <iostream>
//#include <queue>
//#include <string>

using namespace std;
int Q, M, N, S;

using ll = long long;

// 状态压缩
ll input[10005][40];

short output[505];

bool hasloop;

struct node {
    int op = 0; // 0 not, 1 and, 2 or, 3 xor, 4 nand, 5 nor
    int from[7]; // 如果从器件得到是整数,如果是从 input 得到是负数
}elem[505];

int res[505]; // 运算结果, 如果结果未初始化是 0,初始化了是 1/-1

void mset(int t, int i) {
    int index = i / 64;
    int loc = i % 64;
    input[t][index] |= (1 << loc);
}

int read(int t, int i) {
    --i;
    int index = i / 64;
    int loc = i % 64;
    return (input[t][index] >> loc) & 0x1;
}

bool vis[505];
void test() {
    memset(vis, 0, sizeof(vis));
    hasloop = false;
    for (int i = 1; i <= N; ++i) {
        if (vis[i]) continue;
        queue<int> q;
        q.push(i);
        int mvis[505];
        memset(mvis, 0, sizeof(mvis));
        mvis[i] = true;
        while(!q.empty()) {
            int f = q.front(); q.pop();
            for (int j = 0; j < 5; ++j) {
                if (elem[f].from[j] == 0) break;
                if (elem[f].from[j] > 0) {
                    int to  = elem[f].from[j];
                    if (mvis[to]) {
                        hasloop = true;
                        return;
                    }
                    if (vis[to]) continue;
                    vis[to] = mvis[to] = true;
                    q.push(to);
                }
            }
        }
    }
}

int getRes(int no, int t) {
//    cout << "no = " << no << ", op = " << elem[no].op << endl << "input: " << endl;
//    for (int i = 0; i < 5; ++i) {
//        cout << elem[no].from[i] << ", ";
//    }
//    cout << endl;
    if (res[no] != 0) return res[no] == 1 ? 1 : 0;
    int fv[5];
    memset(fv, 0, sizeof(fv));
    int cnt = 0;
    for (int i = 0; i < 5; ++i) {
        if (elem[no].from[i] == 0) break;
        if (elem[no].from[i] < 0) {
            fv[i] = read(t, -elem[no].from[i]);
        } else {
            fv[i] = getRes(elem[no].from[i], t);
        }
        cnt++;
    }
    int v = fv[0];
    switch (elem[no].op) {
        case 0:
            v = !v; break;
        case 1:
            while (--cnt) {
                v &= fv[cnt];
            }
            break;
        case 2:
            while (--cnt) {
                v |= fv[cnt];
            }
            break;
        case 3:
            while (--cnt) {
                v ^= fv[cnt];
            }
            break;
        case 4:
            while (--cnt) {
                v &= fv[cnt];
            }
            v = !v;
            break;
        case 5:
            while (--cnt) {
                v |= fv[cnt];
            }
            v = !v;
            break;

    } // end switch
    if (v == 0) res[no] = -1;
    else res[no] = 1;
//    cout << "no = " << no  << ", res = " << res[no] << endl;
    return v;
}

void solve() {
    cin >> M >> N;
    memset(elem, 0, sizeof(elem));
    for (int i = 1; i <= N; ++i) {
        string func;
        int k;
        string op;
        cin >> func >> k;
        if (func == "AND") elem[i].op = 1;
        else if (func == "OR") elem[i].op = 2;
        else if (func == "XOR") elem[i].op = 3;
        else if (func == "NAND") elem[i].op = 4;
        else if (func == "NOR") elem[i].op = 5;
        for (int j = 0; j < k; ++j) {
            cin >> op;
            int t = atoi(op.substr(1).c_str());
            if (op[0] == 'I') {
                elem[i].from[j] = -t;
            } else {
                elem[i].from[j] = t;
            }
        }
    }
    // part 2
    memset(input, 0, sizeof(input));
    cin >> S;
    for (int i = 0; i < S; ++i) {
        int bit;
        for (int j = 0; j < M; ++j) {
            cin >> bit;
            if (bit) {
                mset(i, j);
            }
        }
    }
    // 测试是否有环
    test();
    if (hasloop) {
        cout << "LOOP" << endl;
    }

    for (int t = 0; t < S; ++t) {
        int s;
        cin >> s;
        for (int j = 0; j < s; ++j) {
            cin >> output[j];
        }
        if (!hasloop) {
            memset(res, 0, sizeof(res));
            for (int j = 0; j < s; ++j) {
                cout << getRes(output[j], t) << " ";
            }
            cout << endl;
        }
//        cout << "debug::" << endl;
//        for (int k = 1; k <= N; ++k) {
//            cout << getRes(k, t) << " ";
//        }
//        cout << endl << endl;
    }
}


int main() {
    cin >> Q;
    while(Q--) solve();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值