当前位置: 代码迷 >> 综合 >> 博弈搜索练习--POJ-2003 Hire and Fire
  详细解决方案

博弈搜索练习--POJ-2003 Hire and Fire

热度:15   发布时间:2023-12-23 17:33:47.0

公司里的那点事儿

描述

对于一间公司来说,它成立之时所做的第一件事恐怕就是任命CEO了。之后,CEO就会开始雇用员工,也会有员工离职去别的公司。假设公司中的每一个员工(包括 CEO在内)都可以直接雇用新的员工,而公司中的所有员工(包括CEO)也都可能会跳槽离开,则某公司在成立一段时间之后的的组织结构如图1:


VonNeumann是公司的CEO,他直接雇用了两个人,分别是Tanenbaum和Dijkstra。在公司中,某员工的几个直接下属,他们的职位是由员工们的工龄决定的,在图中即表现为从从左至右职位越来越低,譬如Tanenbaum的职位就比Dijkstra要高。

当一个员工雇用了新的下属时,该下属在该员工雇佣的所有下属中,职位是最低的。假设VonNeumann又雇用了Shannon,则VonNeumann的三名下属职位从高到低分别是Tanenbaum、Dijkstra和Shannon。

当公司中的员工离职,则有两种情况。若他没有雇用任何下属,则他会被从公司的组织结构中拿掉。若他有直接的下属,则他的直接下属中职位较高的人,会升职并补上缺位。而该下属若也有下属,则他的下属中职位最高的,会补上他升值后空出的位子。以此类推,直到某个尚未雇用下属的员工升职。

假设图1中的Tanenbaum跳槽离开了,则Stallings会补上它的位置,而Knuth会补上Stallings的位置。图2图3分别展示了基于图1的两种的操作的结果。图2: VonNeumann雇用了Shannon。图3: Tanenbaum跳槽。



输入

输入的第一行是 CEO 的姓名。题目中所有的人名的长度都在2-20之间,且由大小写字母、数字和短线(减号)组成。每个名字都包含至少一个大写和一个小写字母。

在第一行后会有很多行内容,他们由如下的规则构成:

  • [老员工] hires [新员工]
  • fire [老员工]
  • print

[老员工] 是已经在公司工作的人的名字,而[新员工]是即将被雇用的员工的名字。以上三种规则组成的内容可能会按照任何顺序出现。但公司中会至少有一名员工(CEO),且公司的规模最大不会超过 1000 人。

输出

对于每一个打印命令,按照如下规则输出当前公司的结构信息:

  • 每一行包含一个人名
  • 第一行是CEO的名字,从第一列开始
  • 对于图4形式的树

  • 输出如下
  • VonNeumann
    +Tanenbaum
    ++Stallings
    +++Knuth
    +++Hamming
    +++Huffman
    ++Silberschatz
    +Dijkstra
  • *关于print的说明:从ceo开始打印,职位每降低一个等级(参考图片和输出),在名字前面加上一个加号。先序(自己->左枝->右枝)输出整棵树的节点。整棵树遍历完之后输出一行"---------"(具体长度看测试用例1)。
  • 输入以EOF结束
  测试输入关于“测试输入”的帮助 期待的输出关于“期待的输出”的帮助 时间限制关于“时间限制”的帮助 内存限制关于“内存限制”的帮助 额外进程关于“{$a} 个额外进程”的帮助
测试用例 1 以文本方式显示
  1. VonNeumann?
  2. VonNeumann hires Tanenbaum?
  3. VonNeumann hires Dijkstra?
  4. Tanenbaum hires Stallings?
  5. Tanenbaum hires Silberschatz?
  6. Stallings hires Knuth?
  7. Stallings hires Hamming?
  8. Stallings hires Huffman?
  9. print?
  10. VonNeumann hires Shannon?
  11. fire Tanenbaum?
  12. print?
  13. fire Silberschatz?
  14. fire VonNeumann?
  15. print?
以文本方式显示
  1. VonNeumann?
  2. +Tanenbaum?
  3. ++Stallings?
  4. +++Knuth?
  5. +++Hamming?
  6. +++Huffman?
  7. ++Silberschatz?
  8. +Dijkstra?
  9. ------------------------------------------------------------?
  10. VonNeumann?
  11. +Stallings?
  12. ++Knuth?
  13. +++Hamming?
  14. +++Huffman?
  15. ++Silberschatz?
  16. +Dijkstra?
  17. +Shannon?
  18. ------------------------------------------------------------?
  19. Stallings?
  20. +Knuth?
  21. ++Hamming?
  22. +++Huffman?
  23. +Dijkstra?
  24. +Shannon?
  25. ------------------------------------------------------------?
1秒 64M 0


题意:略过。

题解:刚看到这题实在不懂这跟博弈搜索练习有什么关系,看了POJ2003的题解感觉这纯粹是在考对数据结构的掌握,尤其是对C++的STL里的一些容器的使用。(后来学长讲蒙特卡洛和UCT时说这个是练习我们建招法树用的,这道题中使用的方法可以将多叉树转为二叉树,想想确实很有道理,也很佩服当初是哪位学长找的这题用来训练招法树建立的。)

参考博客:POJ 2003 Hire and Fire (多重链表 树结构 好题)

map,list用的很强,map提供了一种对应关系容器,list提供了链表结构,这比自己写要舒坦多了。

#include<string>
#include<list>
#include<map>
#include<iostream>
using namespace std;struct Tree
{Tree*father;//与父节点相连string name;//本节点的员工名字list<Tree*>sons;//本节点员工的下属
};map<string, Tree*>StrMap;//建立员工名字与其树节点的对应关系,方便后来的查找操作
Tree *CompanyLink;void Print(Tree*cur_node, int range)//打印输出
{if (!cur_node)//说明没有下属了return;for (int i = 0; i<range; i++)printf("+");cout << cur_node->name << endl;list<Tree*>::iterator iter = cur_node->sons.begin();//迭代器iteratorfor (; iter != cur_node->sons.end(); ++iter)//在这里++iter比iter++效率高,详见C++ iterator 前++ 后++ 效率区别Print(*iter, range + 1);
}
int main()
{CompanyLink = new Tree();//开辟内存空间string EmployName, StaffName, op;//上司,下属,处理hires的cin >> EmployName; StrMap[EmployName] = CompanyLink;CompanyLink->name = EmployName;while (cin >> EmployName){if (EmployName != "print"){if (EmployName != "fire")//hires部分应该还是比较好理解的,用指针操作可以直接改值,不然不能改值{cin >> op >> StaffName;Tree*cur_node = StrMap[EmployName];Tree*new_node = new Tree();new_node->name = StaffName;new_node->father = cur_node;cur_node->sons.push_back(new_node);StrMap[StaffName] = new_node;}else{cin >> StaffName;Tree*cur_node = StrMap[StaffName];StrMap.erase(StaffName);while (cur_node->sons.size() != 0)//一个员工晋级了,则他的第一个下属会顶替他的位置,不断重复至没有下属{cur_node->name = cur_node->sons.front()->name;//当前员工的名字被其第一个下属的名字覆盖,使用覆盖操作的好处在于不会改变原有职位的职工从属关系StrMap.erase(cur_node->name);//删去原有的对应关系StrMap[cur_node->name] = cur_node;//更新新的对应关系cur_node = cur_node->sons.front();//当前指针移动到其第一个下属位置}cur_node->father->sons.remove(cur_node);//没有下属了,则要删除list中的当前节点,因为和前一个重复了delete cur_node;//释放内存空间,之前只是切断了list中的链关系,并没有释放掉内存空间 cur_node = NULL;//指到0,防止出错}}else{Print(CompanyLink, 0);printf("------------------------------------------------------------\n");}}return 0;
}







 
 




















































  相关解决方案