题目来源: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 }