PTA L2-3 到底爱不爱我 题解(超详细!!!)
题目 : L2-3 到底爱不爱我
分数 25
古代少女有了心上人时,会悄悄折一条树枝,揪那枝上的叶子,揪一片叶子念一句“爱我”,再揪一片念一句“不爱我”…… 这样揪落最后一片叶子的时候,看看是停在“爱”还是“不爱”。
但聪明的慧娘一眼洞穿,只要数一下叶子有多少片,根据这个数字的奇偶性判断是以“爱”开始还是以“不爱”开始,就总是可以最后落在“爱”上。这个游戏顿时就变得无趣了 —— 真的是文科生制造浪漫,理科生杀死浪漫。
于是有着工科生大脑的慧娘打算另外制作一个更有趣的浪漫游戏。她用不同植物的枝条做成了三种“情枝”:
“专情枝”:是一根有两个分岔的树枝,只有当两个分岔上连接的枝条传过来的情话都是“爱”的时候,这根枝条的根部才传出“爱”;否则树枝根部传出的是“不爱”。
“博爱枝”:也是一根有两个分岔的树枝,只有当两个分岔上连接的枝条传过来的情话都是“不爱”的时候,这根枝条的根部才传出“不爱”;否则树枝根部传出的都是“爱”。
“情变枝”:是没有分岔的一根直枝,如果一端接到“爱”,另一端必须传出“不爱”;反之如果一端接到“不爱”,另一端则会传出“爱”。
慧娘将这些树枝摆放在院子里,布了一个“情阵”,先选一根特殊的枝条作为初试一枝,从这枝条的根部开始,扩散开去,令它们根枝相连。然后她在末梢的枝杈旁随意写下“爱”或“不爱”。现在请你写个程序帮她算出来,在初始一枝的根部,她能得到“爱”还是“不爱”?
输入格式: 输入在第一行中给出正整数 N(≤30),是慧娘制作的情枝数量。这里假设她将所有的情枝从 1 到 N 做好了编号。随后 N 行,第 i 行给出第 i 枝的描述,格式为
类型 左分枝连接的编号 右分枝连接的编号
其中 类型 为 1 代表专情、2 代表博爱、3 代表情变。当然如果是情变枝,则后面跟的是其唯一末端连接的情枝编号,并没有两个分枝的信息。如果一个分枝是末梢,并没有连接其它枝条,则对应编号为 0。
接下来一行中给出正整数 K(≤30),是慧娘询问的次数。以下 K 行,每行给出一个由 0 和 1 组成的字符串,其中 0 表示“不爱”,1 表示“爱”—— 这是慧娘从左到右在每个枝杈末梢处写下的。(注意:“从左到右”的意思是,我们从初试一枝出发去遍历所有枝条的末梢时,总是遵循先遍历左边情阵、再遍历右边情阵的顺序)
输出格式:
对慧娘的每个询问,如果她在初始一枝的根部能得到“爱”,就输出 Ai;否则输出 BuAi。
输入样例:
6
2 6 4
1 0 0
3 1
2 0 0
3 0
1 5 2
5
11111
00000
11100
10011
01100
输出样例:
BuAi
Ai
Ai
BuAi
BuAi
样例说明:
样例对应的情阵以及慧娘第 3 问的情势如图所示,其中完整的心对应 1,裂开的心对应 0。
解题思路
1.将各个结点存至二维数组,格式为[node,lchild,rchild],若右结点不存在,则存入-1;
2.遍历各个节点,以该节点为根结点构建二叉树
static inline void CreateBinaryTree(BinaryTree &Tree,int p){
if(p == -1){
Tree = NULL;
return;
}
Tree = new BinaryNode;
Tree->data = List[p][0];
CreateBinaryTree(Tree->lchild,List[p][1]);
CreateBinaryTree(Tree->rchild,List[p][2]);
}
3.由于不同结点作为根结点所构成的二叉树结点数量不同,所以必须对树进行遍历,找到该树的结点个数,与预期的结点个数进行比较(预期结点个数为 n + 叶子结点个数),直至找到相匹配的根结点
static inline bool FindTree(BinaryTree &Tree,int p,int num){
CreateBinaryTree(Tree,p);
if(CountNode(Tree) == num)return true;
return false;
}
static inline int CountNode(BinaryTree Tree){
if(Tree)return CountNode(Tree->lchild) + CountNode(Tree->rchild) + 1;
else return 0;
}
4.经过以上步骤,根据输入构建出一棵正确的二叉树,接下来,需要将询问的叶子结点加入二叉树中,利用递归配合位运算符层层推至根结点,得出答案
static inline bool Res(BinaryTree &CalTree){
if(CalTree->lchild && !CalTree->rchild){
return !Res(CalTree->lchild);
}
else if(CalTree->lchild && CalTree->rchild){
if(Function[CalTree->data] == 1){
return Res(CalTree->lchild) & Res(CalTree->rchild);
}
else if(Function[CalTree->data] == 2){
return Res(CalTree->lchild) | Res(CalTree->rchild);
}
}
else if(!CalTree->lchild && !CalTree->rchild){
return LeafInput[p++];
}
}
5.加上主函数,华丽结束
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,k;
cin >> n;
vector<BinaryTree>node(n+1);
List.resize(n+1,vector<int>(3,-1));
Function.resize(n+1);
List[0][0] = 0;
int node_num = n , leaf = 0;
for(int i=1;i<=n;i++){
int fun;
cin >> fun;
Function[i] = fun;
if(fun == 1){
List[i][0] = i;
cin >> List[i][1] >> List[i][2];
if(!List[i][1])leaf++;
if(!List[i][2])leaf++;
}
else if(fun == 2){
List[i][0] = i;
cin >> List[i][1] >> List[i][2];
if(!List[i][1])leaf++;
if(!List[i][2])leaf++;
}
else{
List[i][0] = i;
cin >> List[i][1];
if(!List[i][1])leaf++;
}
}
node_num = node_num + leaf;
BinaryTree Tree , CalTree;
for(int i=1;i<=n;i++){
if(FindTree(Tree,i,node_num)){
break;
}
}
string line;
LeafInput.resize(leaf);
cin >> k;
for(int i=0;i<k;i++){
Reset(Tree,CalTree);
cin >> line;
for(int j=0;j<leaf;j++){
LeafInput[j] = line[j] - '0';
}
cout << (Res(CalTree)?"Ai":"BuAi") << endl;
p = 0;
}
return 0;
}
“蒟蒻的第一篇博客”
“荔枝成为ACM大犇”
完整代码
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef struct Node{
int data;
struct Node *lchild,*rchild;
}*BinaryTree,BinaryNode;
static vector<vector<int>>List;
static vector<int>Function;
static vector<int>LeafInput;
static int p;
static inline void CreateBinaryTree(BinaryTree &Tree,int p);
static inline void Reset(BinaryTree &Tree,BinaryTree &NewTree);
static inline bool FindTree(BinaryTree &Tree,int p,int num);
static inline int CountNode(BinaryTree Tree);
static inline bool Res(BinaryTree &CalTree);
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n,k;
cin >> n;
vector<BinaryTree>node(n+1);
List.resize(n+1,vector<int>(3,-1));
Function.resize(n+1);
List[0][0] = 0;
int node_num = n , leaf = 0;
for(int i=1;i<=n;i++){
int fun;
cin >> fun;
Function[i] = fun;
if(fun == 1){
List[i][0] = i;
cin >> List[i][1] >> List[i][2];
if(!List[i][1])leaf++;
if(!List[i][2])leaf++;
}
else if(fun == 2){
List[i][0] = i;
cin >> List[i][1] >> List[i][2];
if(!List[i][1])leaf++;
if(!List[i][2])leaf++;
}
else{
List[i][0] = i;
cin >> List[i][1];
if(!List[i][1])leaf++;
}
}
node_num = node_num + leaf;
BinaryTree Tree , CalTree;
for(int i=1;i<=n;i++){
if(FindTree(Tree,i,node_num)){
break;
}
}
string line;
LeafInput.resize(leaf);
cin >> k;
for(int i=0;i<k;i++){
Reset(Tree,CalTree);
cin >> line;
for(int j=0;j<leaf;j++){
LeafInput[j] = line[j] - '0';
}
cout << (Res(CalTree)?"Ai":"BuAi") << endl;
p = 0;
}
}
static inline void CreateBinaryTree(BinaryTree &Tree,int p){
if(p == -1){
Tree = NULL;
return;
}
Tree = new BinaryNode;
Tree->data = List[p][0];
CreateBinaryTree(Tree->lchild,List[p][1]);
CreateBinaryTree(Tree->rchild,List[p][2]);
}
static inline void Reset(BinaryTree &Tree,BinaryTree &NewTree){
if(Tree){
NewTree = new BinaryNode;
NewTree->data = Tree->data;
Reset(Tree->lchild,NewTree->lchild);
Reset(Tree->rchild,NewTree->rchild);
}
else{
NewTree = NULL;
return;
}
}
static inline bool FindTree(BinaryTree &Tree,int p,int num){
CreateBinaryTree(Tree,p);
if(CountNode(Tree) == num)return true;
return false;
}
static inline int CountNode(BinaryTree Tree){
if(Tree)return CountNode(Tree->lchild) + CountNode(Tree->rchild) + 1;
else return 0;
}
static inline bool Res(BinaryTree &CalTree){
if(CalTree->lchild && !CalTree->rchild){
return !Res(CalTree->lchild);
}
else if(CalTree->lchild && CalTree->rchild){
if(Function[CalTree->data] == 1){
return Res(CalTree->lchild) & Res(CalTree->rchild);
}
else if(Function[CalTree->data] == 2){
return Res(CalTree->lchild) | Res(CalTree->rchild);
}
}
else if(!CalTree->lchild && !CalTree->rchild){
return LeafInput[p++];
}
}