ZOJ 3805--解题报告
题目相关:
3805相关链接: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5337
在二维的矩形上, 机器通过管道(pipe)连接(I型, L型),最终成为一个系统.

其规则大致提炼如下:
1). 编号大的输出可以成为编号小的输入(隐含拓扑序), 编号1只有输入/没有输出.
2). 每个节点最多有两个输入(弱化的图, 可以用二叉树来模拟)
3). 矩形世界没有高度限制, 但有宽度限制
目标就是:
最能满足要求的最小宽度是多少?
思路解析:
本题隐含拓扑序(有向图), 同时每个节点最多两个子节点, 因此我们采用二叉树去模拟. 这种最优化问题, 有可能是动态规划(树形DP), 通过观察和琢磨. 可得出如下结论:
如果节点i存在子节点j, k, 若节点j的宽度==节点k的宽度, 则取子节点宽度+1, 若子节点不相同, 则取子节点最大宽度的.
转化为公式如下:
{ node(j) + 1; if node(j) == node(k) --(1)
node(i) = {
{ max(node(j), node(k)); if node(j) != node(k) --(2)
其二叉树的是偏向树, 构建的时候, 往一个方向倾斜就是了.
AC代码:
#include <cstdio> #include <vector>
#include <stack> #include <functional> struct tree_node_t {
int left_index;
int right_index;
int value;
tree_node_t(int li = -1, int ri = -1, int v = -1)
: left_index(li), right_index(ri), value(v) {
}
}; class machine {
public:
machine() {
} // *) 输入数据并构建二叉树
void init_and_buildtree(int n, const std::vector<int> &datas) {
arr_tree.resize(n);
for ( int i = 1; i < datas.size(); i++ ) {
int idx = datas[i] - 1;
if ( arr_tree[idx].left_index == -1 ) {
arr_tree[idx].left_index = i;
} else {
arr_tree[idx].right_index = i;
}
}
} // *) 计算结果
// *) 这边采用模拟堆栈的方式, 来实现递归调用, 因为节点有10000个.
// *)最差情况会导致二叉树成链表, 导致递归的调用栈达到10000
int calculator() { std::stack<int> frames;
frames.push(0);
while ( !frames.empty() ) {
int idx = frames.top(); const int &li = arr_tree[idx].left_index;
const int &ri = arr_tree[idx].right_index; if ( li != -1 && arr_tree[li].value == -1 ) {
frames.push(li);
} else if ( ri != -1 && arr_tree[ri].value == -1 ) {
frames.push(ri);
} else {
if ( li == -1 ) {
arr_tree[idx].value = 1;
} else if ( li != -1 && ri == -1 ) {
arr_tree[idx].value = arr_tree[li].value;
} else if ( li != -1 && ri != -1 ) {
if ( arr_tree[li].value == arr_tree[ri].value ) {
arr_tree[idx].value = arr_tree[li].value + 1;
} else {
arr_tree[idx].value =
std::max(arr_tree[li].value, arr_tree[ri].value);
}
}
frames.pop();
} }
return arr_tree[0].value; } public:
std::vector<tree_node_t> arr_tree;
}; int main()
{ int n;
while ( scanf("%d", &n) != EOF ) {
std::vector<int> datas(n, 0);
for ( int i = 1; i < n; i++ ) {
scanf("%d", &datas[i]);
} machine instance;
instance.init_and_buildtree(n, datas); printf("%d\n", instance.calculator());
}
return 0; }
评注: 这边采用堆栈的方式来模拟递归调用, 是因为担心堆栈太深, 不过实际测试数据集, 没那么变态, 用递归的方式实现, 不仅优雅而且编码效率更高.
递归代码片段:
// *) 递归函数, 划分子问题
int evaluate(int idx) { int li = arr_tree[idx].left_index;
int ri = arr_tree[idx].right_index;
if ( li != -1 ) {
evaluate(li);
}
if ( ri != -1 ) {
evaluate(ri);
} if ( li == -1 ) {
return arr_tree[idx].value = 1;
} else if ( li != -1 && ri == -1 ) {
return arr_tree[idx].value = arr_tree[li].value;
} else {
if ( arr_tree[li].value == arr_tree[ri].value ) {
arr_tree[idx].value = arr_tree[li].value + 1;
} else {
arr_tree[idx].value = std::max(arr_tree[li].value, arr_tree[ri].value);
}
} return arr_tree[idx].value; } // *) 驱动函数
int calculator() {
return evaluate(0);
}
ZOJ 3805--解题报告的更多相关文章
- ZOJ 1093 Monkey and Banana (LIS)解题报告
ZOJ 1093 Monkey and Banana (LIS)解题报告 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid= ...
- zoj 2313 Chinese Girls' Amusement 解题报告
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1313 题目意思:有 N 个人(编号依次为1~N)围成一个圆圈,要求求 ...
- CH Round #56 - 国庆节欢乐赛解题报告
最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...
- 二模13day1解题报告
二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...
- BZOJ 1051 最受欢迎的牛 解题报告
题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4438 Solved: 2353[S ...
- 习题:codevs 2822 爱在心中 解题报告
这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...
- 习题:codevs 1035 火车停留解题报告
本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...
- 习题: codevs 2492 上帝造题的七分钟2 解题报告
这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...
- 习题:codevs 1519 过路费 解题报告
今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...
- NOIP2016提高组解题报告
NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合
随机推荐
- 常州培训 day7 解题报告
最后一天..有些感慨,这七天被虐的感动万分 第一题: 题目大意: 求出 n*i(i=1,2,3....n) mod p的逆元 n<p<=3000000 ,p是质数. 之前写过了,懒得再写 ...
- synergy配置 Ubuntu作Server, Win 7作client
Synergy 允许你轻松地在你办公桌上多台计算机之间共享你的鼠标和键盘,它免费并且开放源代码.你只要将鼠标(指针)从一台计算机的屏幕边缘移出到另一个屏幕就行 了.甚至可以共享你的剪贴板.你所需要的仅 ...
- 创建ROS功能包(四)
为了方便直接用ROS的create-pkg命令行工具 roscreate-pkg chapter2_tutorials std_msgs rospy roscpp std_msgs 包含了常见的消息类 ...
- convert2Mp4 code snippet
#pragma mark - helper - (NSURL *)convert2Mp4:(NSURL *)movUrl { NSURL *mp4Url = nil; AVURLAsset *avAs ...
- [开发笔记]-flowplayer视频播放插件
最近项目中需要添加播放视频的功能,视频文件是flv格式的.在网上找了一些jQuery视频播放插件,还是觉得“flowplayer”要好一些.特将使用方法记录一下. flowplayer也有html5版 ...
- jquery easyui DataGrid 动态的改变列显示的顺序
$.extend($.fn.datagrid.methods,{ columnMoving: function(jq){ return jq.each(function(){ var target = ...
- Flux Demo解析
最近学习了阮一峰老师的博文 "Flux入门教程",博文中详细介绍了Flux框架和Controller view模式,并提供了Demo,受益匪浅. 现特参考阮老师的Demo,绘制了一 ...
- 黑马程序员——OC语言Foundation框架 结构体
Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)结构体 NSRange(location length) NSPoi ...
- git——学习笔记(三)分支管理
一.创建.合并分支 每次提交,git都往后走一格,串成一跳时间线,head指向的是分支,分支指向提交.master是主分支,dev是另一条分支,分支就像指针一样,合并.删除分支时,修改的都是指针,工作 ...
- android 经典下雨效果
英文原文地址:https://blog.stylingandroid.com/snowfall/ 中文翻译地址:http://www.open-open.com/lib/view/open145226 ...