PTA L2-3 到底爱不爱我 题解

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++];
    }
}

  • 25
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值