ACM学习历程—NPU 2015年陕西省程序设计竞赛网络预赛(正式赛)A题 小女警的异世界之战(dfs && 分治)...

Description

这一天,小女警花花,泡泡和毛毛来到终极Boss"Him"所在的异世界并准备与其决一死战,却被困在了他的城堡里。她们发现异世界是一个巨大的城堡。城堡由一个个大小不同的房间组成,房间有着以下的规则:

  1. 每个房间有且仅有一扇黄门,此外至多有一扇红门和一扇绿门:黄色代表通向更大的房间,绿色和红色代表通向更小的房间。很显然,如果你打开了一扇红/绿色的门,你会发现门的背面是黄色的,反之同理。
  2. 红色和绿色的门都是可以随意打开的,然而黄色的门要等到该房间其他门均被打开过,且该房间怪物已经被杀死时才能被打开。在成功穿过黄门后,这扇门就会消失。
  3. 每个房间都会有一个怪物,小女警可自由挑选打败怪物的时机而不影响其打开该房间的红/绿门。

三位小女警的起点就是一间较为特殊的房间,这个房间与正常房间的区别是黄门是特制的。为了解锁这个房间的特殊黄门,三位小女警必须分别依次探索这个房间的其他门,而每个小女警在探索时,怪物与门的状态都会重置。三位小女警的探索方式有着巨大的差别:

花花对红色有着狂热的痴迷,因此当她看见红门时,会暂时无视怪物而立刻冲进去,但是当所在房间没有红门时,她会恢复理智并优先将所在房间的怪物杀死,然后进入绿门(如果有的话)来解锁黄门。

泡泡有强烈的强迫症而且讨厌绿色,当她看到怪物时一定会将其杀死,然后她会优先开启红门,不得已时她才会进入绿门来解锁黄门。

毛毛有拖延症,因此她会优先去开她喜爱的红色的门,随后去开绿色的门,当其所在房间没有门可开时,她才会通过杀死怪物的方式解锁黄门并回去。

每个房间的怪物都有独一无二的名字,当小女警杀死怪物时,怪物的名字会按顺序被记录在日志上,现在花花和泡泡已经按规则探索过了这个城堡,并回到了出发点,毛毛借来了她们的日志以便预测她将会碰到的怪物的顺序,你能帮助她完成这个任务吗?

 

Input

数据有多组,每组数据以一个数字n(1<=n<=100)为开始,代表有n条记录,

接下来的两行分别是花花和泡泡的日志,分别包含了n个怪物的名字,用空格隔开。

n==0时,输入结束。

 

Output

输出一行毛毛的日志,怪物名字之间用空格隔开。

Sample Input

5
skeleton zombie spider bat witch
bat zombie skeleton spider witch 
0

Sample Output

skeleton spider zombie witch bat

 

题目大意就是告诉你树的中序遍历和先序遍历,输出树的后序遍历。

从先序遍历下手,首先在第二组字符串里最先出现的一定是根节点,然后出现的是左子树的根节点(如果存在的话),依此递归定义。

然后再看第一个字符串,出现在根节点左侧的所有节点一定是左子树的所有节点,出现在右侧的一定是右子树的所有节点。然后看左侧部分,出现在左子树根节点左侧的一定是左子树的左子树的所有节点,依此递归定义。

然后就可以考虑分治了:

先从第二个字符串取出第一个,一定是根,然后在第一个字符串中找出这个节点(此处采用了map进行映射),(1)然后先对左侧进行分治:从第二个字符串取出第二个,同理找出左侧中这个节点,先对左侧的左半部分分治,然后对右半部份分治。(2)然后对右侧进行同样的分治。。。依此递归。树便建成。

 

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>

using namespace std;

struct node
{
    char val[50];
    node *left, *right;
};

int n;
char str1[105][50], str2[105][50];
map <string, int> Hash;
bool flag;

void Input()
{
    Hash.clear();
    for (int i = 0; i < n; ++i)
    {
        scanf("%s", str1[i]);
        Hash[str1[i]] = i;
    }
    for (int i = 0; i < n; ++i)
        scanf("%s", str2[i]);
}

node *Build(int &state, int from, int to)
{
    if (state >= n-1 || from > to)
        return NULL;
    state++;
    if (from == to)
    {
        node *p = (node *)malloc(sizeof(node));
        strcpy(p->val, str2[state]);
        p->left = NULL;
        p->right = NULL;
        return p;
    }

    int k = Hash[str2[state]];
    node *now = (node *)malloc(sizeof(node));
    strcpy(now->val, str2[state]);
    now->left = Build(state, from, k-1);
    now->right = Build(state, k+1, to);
    return now;
}

void Dfs(node *k)
{
    if (k->left != NULL)
        Dfs(k->left);
    if (k->right != NULL)
        Dfs(k->right);
    if (flag)
        printf(" ");
    printf("%s", k->val);
    flag = true;
}

void Work()
{
    node *head;
    int state = -1;
    head = Build(state, 0, n-1);
    flag = false;
    Dfs(head);
    printf("\n");
}

int main()
{
    //freopen("test.in", "r", stdin);
    while (scanf("%d", &n) != EOF && n)
    {
        Input();
        Work();
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/andyqsmart/p/4508522.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值