POJ1048 Follow My Logic

题目来源:http://poj.org/problem?id=1048

题目大意:

  给定一个逻辑电路,求其逻辑输出。电路含一个或多个输入,以及一些双输入的与门/或门组成。电路图以下面形式的ASCII码图给出。 电路中,路径由横线,纵线和折点组成,'-'和'|'表示横线和纵线,'+'表示折点。输入由大写字母A到Z表示,输出由'?'表示。与门和或门的表示方法如图所示,而且它们的朝向时钟与图示一致(不会反向或成竖直方向)。门的输入和输出可以被取“非”,用小写的'o'表示。下图最右为一个简单但完整的电路。

    :\               :\                 -:\                 -o:\                       A-o:\

    : ) : > : )- : )o- : )o-?
    :/ :/ -:/ --:/ B--:/

AND gate OR gate Gate with inputs An inverted top input Two logic inputs
and an inverted output and the output

输入:电路遵循以下规则:

  1. 电路图的最大尺寸为100*100.

  2. 线路始终沿直线,除非遇到折点。折点处,路径转弯90°,折点不会相邻。

  3. 所有的线路都不会中途中断。

  4. 线路不会相交。

  5. 逻辑门始终如上图所示,输入位于左侧,输出位于右侧。

  6. “非”只会出现在紧邻逻辑门输入或输出的地方,且前面(紧邻输入时)或后面(紧邻输出时)接有至少一个'-'或'|'.

  遇到只含一个'*'的一行时,表示电路图结束,后面为电路图输入状态。每个输入由一行组成,为一个由26个0或1组成的串。第一个数为A的值,第二个为B,以此类推。给定的输入值中电路图里没有用到的应被忽略。"*"表示输入状态结束。

  接下来是另一副电路图和新的输入状态,直到遇到end of file. 文件中至少含有一个电路图和一组输入状态。

输出:程序输出每个电路图对每个输入状态的逻辑输出值。每个输入状态单独一行,每个电路图的输出之间用空格隔开。


Sample Input

A---:\
    : )---?
B---:/
*
00000000000000000000000000
10000000000000000000000000
01000000000000000000000000
11000000000000000000000000
*
A---+
    |    
    +---:\
        : >o---:\
    +---:/     : )---?
    |      C--o:/
B---+
*
00000000000000000000000000
11100000000000000000000000
*

Sample Output

0
0
0
1

1
0

 首先读入整幅电路图,找到电路图输出的位置,然后递归分析电路图的逻辑结构,构造一颗逻辑树。然后对于每个输入状态根据逻辑树去递归求值即可。但是要注意电路图中线路方向的处理问题,因为图并非一定是规矩的沿从左至方向,线路可能弯折。比如下面的例子:

A-+
  |
  o:\
   : )-?
B--:/

A---+
    |    
    +---:\
        : >o---:\
    +---:/     : )---?
    |      C--o:/
    +---+
        |
B-------+
  1 //
  2 //        POJ1048 Follow My Logic
  3 //        Memory: 180K        Time: 0MS
  4 //        Language: C++        Result: Accepted
  5 //
  6 
  7 #include <iostream>
  8 #include <cstdio>
  9 
 10 using namespace std;
 11 
 12 char circuit[105][105];
 13 int h;
 14 int x, y;
 15 
 16 enum DIR {
 17     LEFT, UP, RIGHT, DOWN
 18 };
 19 
 20 struct Node {
 21     int type;    //0-25表示对应输入状态的序号(A-Z); -2 and; -3 or; -4 not.
 22     int left_child;
 23     int right_child;
 24 };
 25 
 26 Node tree[400];
 27 int tree_len;
 28 
 29 char input[27];
 30 
 31 bool ReadCircuit() {
 32     memset(circuit, 0, sizeof(circuit));
 33     if (!gets(circuit[0])) return false;
 34     h = 1;
 35     while (gets(circuit[h++])) {
 36         if (circuit[h - 1][0] == '*') {
 37             --h;
 38             break;
 39         }
 40     }
 41     return true;
 42 }
 43 
 44 void FindOutput() {
 45     for (int i = 0; i < h; ++i) {
 46         for (int j = 0; j < 100; ++j) {
 47             if (circuit[i][j] == '\0') break;
 48             if (circuit[i][j] == '?') {
 49                 x = i;
 50                 y = j;
 51                 return;
 52             }
 53         }
 54     }
 55 }
 56 
 57 void ConstructTree(int x, int y, int node_id, DIR dir) {
 58     switch (circuit[x][y]) {
 59         case '?':
 60             if (circuit[x][y - 1] == '-') ConstructTree(x, y - 2, node_id, LEFT);
 61             else if (circuit[x][y + 1] == '-') ConstructTree(x, y + 2, node_id, RIGHT);
 62             else if (circuit[x - 1][y] == '|') ConstructTree(x - 2, y, node_id, UP);
 63             else if (circuit[x + 1][y] == '|') ConstructTree(x + 2, y, node_id, DOWN);
 64             else ConstructTree(x, y - 1, node_id, LEFT);
 65             break;
 66         case ')':
 67             tree[node_id].type = -2;    //and
 68             tree[node_id].left_child = ++tree_len;
 69             tree[node_id].right_child = ++tree_len;
 70             ConstructTree(x - 1, y - 3, tree[node_id].left_child, LEFT);
 71             ConstructTree(x + 1, y - 3, tree[node_id].right_child, LEFT);
 72             break;
 73         case '>':
 74             tree[node_id].type = -3;    //or
 75             tree[node_id].left_child = ++tree_len;
 76             tree[node_id].right_child = ++tree_len;
 77             ConstructTree(x - 1, y - 3, tree[node_id].left_child, LEFT);
 78             ConstructTree(x + 1, y - 3, tree[node_id].right_child, LEFT);
 79             break;
 80         case 'o':
 81             tree[node_id].type = -4;    //not
 82             tree[node_id].left_child = ++tree_len;
 83             tree[node_id].right_child = -1;
 84             if (circuit[x][y - 1] == ')' || circuit[x][y - 1] == '>') 
 85                 ConstructTree(x, y - 1, tree[node_id].left_child, LEFT);
 86             else if (circuit[x][y - 1] == '-' && dir != RIGHT) 
 87                 ConstructTree(x, y - 2, tree[node_id].left_child, LEFT);
 88             else if (circuit[x][y + 1] == '-' && dir != LEFT) 
 89                 ConstructTree(x, y - 2, tree[node_id].left_child, RIGHT);
 90             else if (circuit[x - 1][y] == '|' && dir != DOWN) 
 91                 ConstructTree(x - 2, y, tree[node_id].left_child, UP);
 92             else ConstructTree(x + 2, y, tree[node_id].left_child, DOWN);
 93             break;
 94         case '+':
 95             if (dir == UP || dir == DOWN) {
 96                 if (circuit[x][y - 1] == '-') ConstructTree(x, y - 2, node_id, LEFT);
 97                 else ConstructTree(x, y + 2, node_id, RIGHT);
 98             } else {
 99                 if (circuit[x - 1][y] == '|')ConstructTree(x - 2, y, node_id, UP);
100                 else ConstructTree(x + 2, y, node_id, DOWN);
101             }
102             break;
103         case '-':
104             if (dir == LEFT) ConstructTree(x, y - 1, node_id, LEFT);
105             else ConstructTree(x, y + 1, node_id, RIGHT);
106             break;
107         case '|':
108             if (dir == UP) ConstructTree(x - 1, y, node_id, UP);
109             else ConstructTree(x + 1, y, node_id, DOWN);
110             break;
111         default:
112             tree[node_id].left_child = -1;
113             tree[node_id].right_child = -1;
114             tree[node_id].type = circuit[x][y] - 'A';
115     }
116 }
117 
118 bool GetInput() {
119     scanf("%s", input);
120     if (input[0] == '*') return false;
121     return true;
122 }
123 
124 int GetOutput(int i) {
125     switch (tree[i].type) {
126         case -2:    //and
127             return GetOutput(tree[i].left_child) && GetOutput(tree[i].right_child);
128         case -3:    //or
129             return GetOutput(tree[i].left_child) || GetOutput(tree[i].right_child);
130         case -4:    //not
131             return !GetOutput(tree[i].left_child);
132         default:
133             return input[tree[i].type] - '0';
134     }
135 }
136 
137 int main(){
138     while (ReadCircuit()){
139         FindOutput();
140         tree_len = 0;
141         ConstructTree(x, y, 0, LEFT);
142         while (GetInput()) {
143             printf("%d\n", GetOutput(0));
144         }
145         printf("\n");
146     }
147     return 0;
148 }
View Code

转载于:https://www.cnblogs.com/dengeven/p/3248948.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值