题目背景
土豪大学的计算机系开了一门数字逻辑电路课,第一个实验叫做“点亮数字人生”,要用最基础的逻辑元件组装出实际可用的电路。时间已经是深夜了,尽管实验箱上密密麻麻的连线已经拆装了好几遍,小君同学却依旧没能让她的电路正常工作。你能帮助她模拟出电路的功能,成功点亮她的数字人生吗?
问题描述
本题中,你需要实现一个简单的数字逻辑电路模拟器。如果你已经有了此方面的基础,可以直接跳过本节。在阅读时,也可以参照前两个样例的图示和解释,这有助于你更好地理解数字逻辑电路的工作原理。
数字逻辑电路是用来传输数字信号(也就是二进制信号)的电路。一般来说,数字逻辑电路可以分为两大类,即组合逻辑(combinational logic)电路和时序逻辑(sequential logic)电路。在本题中,我们仅关注组合逻辑电路。这种电路仅由逻辑门(logical gate)构成。一个逻辑门可以理解为一个多输入单输出的函数,输入端连接至少一个信号,而后经过一定的逻辑运算输出一个信号。常见的逻辑门包括与(AND)、或(OR)、非(NOT)、异或(XOR)等,均与编程语言中的按位运算是对应的。
将一系列的逻辑门连接起来,就能构成具有特定功能的电路。它的功能可能很简单(如一位二进制加法只需要一个异或门),也可能极其复杂(如除法)。无论复杂程度,这类电路的特点是:它不维持任何的状态,任何时刻输出只与输入有关,随输入变化。真实世界中的逻辑器件由于物理规律的限制,存在信号传播延时。为了简单起见,本题中我们模拟的组合逻辑电路不考虑延时:一旦输入变化,输出立刻跟着变化。
考虑到组合逻辑电路的这一特性,设计时不能允许组合环路(combinational loop)的存在,即某逻辑门的输入经过了一系列器件之后又被连接到了自己的输入端。真实世界中,这种做法将导致电路变得不稳定,甚至损坏元器件。因此,你也需要探测可能的环路。需要注意,环路的存在性与逻辑门的具体功能没有任何关系;只要连接关系上存在环路,电路就无法正常工作。
感想:考试的时候读电路输入输出的时候以为编号只有一位,然后读入时只读了一个数字,实际上是可以有O10 , I100这样的读入,读的时候可以用字符串流或者sscanf。
思路:先按照给出的电路图存图,然后dfs模拟即可,还有一个小坑是只要图有环,就算要输出的部分不涉及环路也判LOOP(我最开始只判断要输出的部分,得了80分),判环可以用拓扑排序,或者直接dfs加标记即可
代码:
dfs + 拓扑排序判环
#include
using namespace std;
const int maxn = 705 , N = 2e4 + 5;
struct gate{
string func;
vector <int> ii;
vector <int> o;
int out;
gate() {
out;
}
gate(string s) : func(s){}
};
int tin[N][maxn * 6] , tout[N] , mout[maxn] , in[N];
int vis[maxn];
vector <int> ans[N];
vector <gate> g;
bool dfs(int u , int k ) {
//if(vis[u]) return false;
if(mout[u] != -1)return mout[u];
int res = 0;
if(g[u].func[0] == 'X') {
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res ^= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res ^= mout[v];
}
mout[u] = res;
//cout << "u = " << u << "res = " << res << endl;
}
else if(g[u].func[0] == 'A') {
res = 1;
bool flag = 0;
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res &= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res &= mout[v];
}
mout[u] = res;
}
else if(g[u].func[0] == 'O') {
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res |= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res |= mout[v];
}
mout[u] = res;
}
else if(g[u].func == "NOT") {
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res = !tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res = !mout[v];
}
mout[u] = res;
}
else if(g[u].func == "NAND") {
res = 1;
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res &= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res &= mout[v];
}
mout[u] = !res;
}
else {
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res |= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res |= mout[v];
}
mout[u] = !res;
}
return true;
}
bool tp(int n ) {
for(int i = 1 ; i <= n ; i++) {
for(int j = 0; j < g[i].o.size() ; j++) {
int v = g[i].o[j];
in[v]++;
}
}
queue <int> q;
int cnt = 0;
for(int i = 1 ; i <= n ; i++) {
if(!in[i]) {
cnt++;
q.push(i);
}
}
while(!q.empty()) {
int u = q.front(); q.pop();
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(in[v] == 1) {
q.push(v);
cnt++;
}
in[v]--;
}
}
if(cnt < n)return false;
else return true;
}
int main() {
int Q;
int m , n;
ios::sync_with_stdio(0);
cin >> Q;
while(Q--) {
cin >> m >> n;
g.clear();
g.push_back(gate());
memset(in , 0 , sizeof(in));
for(int i = 1 ; i <= n ; i++) {
string func;
int k;
cin >> func >> k;
gate g1 = gate(func);
while(k--) {
string s;
cin >> s;
int t = 0;
stringstream ss(s.substr(1));
ss >> t;
if(s[0] == 'O')g1.o.push_back(t);
else if(s[0] == 'I')g1.ii.push_back(t);
}
g.push_back(g1);
}
int s;
cin >> s;
for(int i = 1 ; i <= s ; i++) {
for(int j = 1 ; j <= m ; j++) {
cin >> tin[i][j];
}
}
bool flag = 0;
memset(vis , 0 , sizeof(vis));
if( !tp(n) ) {
flag = 1;
}
for(int i = 1 ; i <= s ; i++) {
int si;
for(int j = 1 ; j <= n ; j++)mout[j] = -1;
cin >> si;
for(int j = 1 ; j <= si ; j++) {
cin >> tout[j];
}
for(int j = 1 ; j <= si && !flag; j++) {
dfs(tout[j] , i);
ans[i].push_back(mout[tout[j]]);
}
}
if(!flag) {
for(int i = 1 ; i <= s ; i++) {
for(int j = 0 ; j < ans[i].size() ; j++) {
if(j > 0)cout << " ";
cout << ans[i][j];
}
cout << "\n";
}
}
else {
cout << "LOOP\n";
}
for(int i = 1 ; i <= s; i++) {
ans[i].clear();
}
}
return 0;
}
dfs + dfs判环:
#include
using namespace std;
const int maxn = 705 , N = 2e4 + 5;
struct gate{
string func;
vector <int> ii;
vector <int> o;
int out;
gate() {
out;
}
gate(string s) : func(s){}
};
int tin[N][maxn * 6] , tout[N] , mout[maxn] , in[N];
int vis[maxn];
vector <int> ans[N];
vector <gate> g;
bool dfs(int u , int k ) {
//if(vis[u]) return false;
if(mout[u] != -1)return mout[u];
int res = 0;
if(g[u].func[0] == 'X') {
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res ^= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res ^= mout[v];
}
mout[u] = res;
//cout << "u = " << u << "res = " << res << endl;
}
else if(g[u].func[0] == 'A') {
res = 1;
bool flag = 0;
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res &= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res &= mout[v];
}
mout[u] = res;
}
else if(g[u].func[0] == 'O') {
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res |= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res |= mout[v];
}
mout[u] = res;
}
else if(g[u].func == "NOT") {
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res = !tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res = !mout[v];
}
mout[u] = res;
}
else if(g[u].func == "NAND") {
res = 1;
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res &= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res &= mout[v];
}
mout[u] = !res;
}
else {
for(int i = 0 ; i < g[u].ii.size() ; i++) {
int v = g[u].ii[i];
res |= tin[k][v];
}
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(mout[v] == -1 ) {
if(!dfs(v , k));//return false;
}
res |= mout[v];
}
mout[u] = !res;
}
return true;
}
bool solve(int u , int f) {
if(vis[u]) {
if( vis[u] == f )return false;
return true;
}
vis[u] = f;
for(int i = 0 ; i < g[u].o.size() ; i++) {
int v = g[u].o[i];
if(!solve(v , f) ) {
return false;
}
}
return true;
}
bool tp(int n ) {
for(int i = 1 ; i <= n ; i++) {
if(!vis[i] && !solve(i , i)) {
return false;
}
}
return true;
}
int main() {
int Q;
int m , n;
ios::sync_with_stdio(0);
cin >> Q;
while(Q--) {
cin >> m >> n;
g.clear();
g.push_back(gate());
memset(in , 0 , sizeof(in));
for(int i = 1 ; i <= n ; i++) {
string func;
int k;
cin >> func >> k;
gate g1 = gate(func);
while(k--) {
string s;
cin >> s;
int t = 0;
stringstream ss(s.substr(1));
ss >> t;
if(s[0] == 'O')g1.o.push_back(t);
else if(s[0] == 'I')g1.ii.push_back(t);
}
g.push_back(g1);
}
int s;
cin >> s;
for(int i = 1 ; i <= s ; i++) {
for(int j = 1 ; j <= m ; j++) {
cin >> tin[i][j];
}
}
bool flag = 0;
memset(vis , 0 , sizeof(vis));
if( !tp(n) ) {
flag = 1;
}
for(int i = 1 ; i <= s ; i++) {
int si;
for(int j = 1 ; j <= n ; j++)mout[j] = -1;
cin >> si;
for(int j = 1 ; j <= si ; j++) {
cin >> tout[j];
}
for(int j = 1 ; j <= si && !flag; j++) {
dfs(tout[j] , i);
ans[i].push_back(mout[tout[j]]);
}
}
if(!flag) {
for(int i = 1 ; i <= s ; i++) {
for(int j = 0 ; j < ans[i].size() ; j++) {
if(j > 0)cout << " ";
cout << ans[i][j];
}
cout << "\n";
}
}
else {
cout << "LOOP\n";
}
for(int i = 1 ; i <= s; i++) {
ans[i].clear();
}
}
return 0;
}