【解题报告】POJ-1108 Split Windows
原题地址:http://poj.org/problem?id=1108
==============================
题目大意:
一棵树表示一个窗口,它的叶子节点都是大写字母,非叶子节点是两种字符‘|’和‘-’,表示它的两棵子树分别位于主窗口的上下和左右。给你一棵树,要求画出窗口。
1.每个叶子结点用一个字母表示,对应图中最小的一个窗口,该窗口的左上角写的是这个字母,其他三个角是*号,但如果这个角是其他窗口的左上角,则要显示对应的字母。窗口的上下边用字符‘-’表示,左右边用字符‘|’表示。
2.可以知道,一个大窗口如果被分为上下两个部分,则上下两个小窗口的宽度是相同的,若被分为左右两个窗口,则高度是相同的。而单独一个小窗口应该是2*2的大小,但如果两部分窗口的宽度(或高度)不能相同,则较小的那个窗口要按比例拉伸且左边的(或上边的)窗口计算出来的大小为小数时,要向上取整。
题目输入时是按照先序遍历的方式输入的。
==============================
解题思路:
思路分为两步:
1、先分别计算出每个子窗口最小的大小(高和宽),按后序遍历的方式,如果是叶子节点,则高和宽都是2,若是‘-’窗口,则该窗口的高等于上窗口加下窗口,宽等于两个窗口的高的较大值。若是‘|’同理。按这样的方式计算出来的长宽不是最终的高宽,但最大的那个窗口的窗口的高和宽就是整个图形的高和宽了。
2、根据各个窗口的高和宽,在一个字符数组里逐条画出分隔窗口每条线(先序遍历)。在计算线的位置的时候要按比例计算出每部分窗口的实际宽度和高度。
==============================
解题过程:
1、数据结构:
#define N 2000
struct NODE
{
char c;//保存窗口的字母或者‘-’和‘|’
int k;//窗口的宽度
int h;//窗口的高度
int l,r;//左孩子和右孩子的数组下标
};
NODE node[N];//保存整个二叉树
char ans[N][N];//保存最终的图形
本来想用数组存二叉树的时候,第i个节点的左孩子用第i*2个节点表示,第2*i+1个节点表示右孩子,但做下去RE了,原因是这个二叉树不是完全二叉树,若所有的节点都只有左孩子,则要用到2^36,则必然放不下,因此改成l,r分别表示该节点的左孩子和右孩子的数组下标。
2、二叉树的输入:
由于该二叉树的输入是按先序遍历的方式,而每个叶子节点都是大写字母,因此,在输入的时候用先序遍历的方式,逐个读取字符,若是叶子节点则返回,若不是,则继续读入左孩子和右孩子。
int k;
int chuli()//输入
{
scanf("%c",&node[k].c);
int n=k;
if(node[n].c=='|'||node[n].c=='-')
{
++k;
node[n].l=k;
chuli();
++k;
node[n].r=k;
chuli();
}
else return ;
}
用k作为全局变量,使输入的树的结点按顺序存储在数组中。
3、计算每个窗口的大小:
int f(int n)//计算每个窗口的大小
{
if(node[n].c<='Z'&&node[n].c>='A')
{
node[n].k=node[n].h=;
return ;
}
f(node[n].l);
f(node[n].r);
if(node[n].c=='|')
{
node[n].k=node[node[n].l].k+node[node[n].r].k;
node[n].h=MAX(node[node[n].l].h,node[node[n].r].h);
}
else
{
node[n].k=MAX(node[node[n].l].k,node[node[n].r].k);
node[n].h=node[node[n].l].h+node[node[n].r].h;
}
return ;
}
后序遍历整个二叉树,如果是叶子节点,则高和宽都是2,若是‘-’窗口,则该窗口的高等于上窗口加下窗口,宽等于两个窗口的高的较大值。
4、根据计算好的每个窗口的大小在字符的二维数组ans里画出整个窗口:
初始化为一个高度为node[1].h,宽度为node[1].k的窗口,四个角都用‘*’表示。
//画外框
ans[][]='*';
for(j=;j<node[].k;j++) ans[][j]='-';
ans[][j]='*';
for(i=;i<node[].h;i++)
{
ans[i][]='|';
for(j=;j<node[].k;j++) ans[i][j]=' ';
ans[i][j]='|';
}
ans[i][]='*';
for(j=;j<node[].k;j++) ans[i][j]='-';
ans[i][j]='*';
画每条线和填入字母:
void pr1(int x,int y,int l)//画竖线,以点(x,y)为上端点,画一条长为l的线,其中,两个端点用‘*’表示。
{
int i;
ans[x][y]='*';
for(i=;i<l;i++)
{
ans[x+i][y]='|';
}
ans[x+i][y]='*';
}
void pr2(int x,int y,int l)//画横线
{
int i;
ans[x][y]='*';
for(i=;i<l;i++)
{
ans[x][y+i]='-';
}
ans[x][y+i]='*';
}
int p(int x,int y,int i)//(x,y)表示当前窗口的左上角的坐标,i表示当前节点的数组下标。
{
//p1();
//getchar();
if(node[i].c=='|')
{
node[node[i].l].h=node[node[i].r].h=node[i].h;
node[node[i].r].k=node[i].k*node[node[i].r].k/(node[node[i].r].k+node[node[i].l].k);
node[node[i].l].k=node[i].k-node[node[i].r].k;//按比例分配宽度
//画竖线
pr1(x,y+node[node[i].l].k,node[i].h);
p(x,y,node[i].l);
p(x,y+node[node[i].l].k,node[i].r);
}
else if(node[i].c=='-')
{
node[node[i].l].k=node[node[i].r].k=node[i].k;
node[node[i].r].h=node[i].h*node[node[i].r].h/(node[node[i].r].h+node[node[i].l].h);
node[node[i].l].h=node[i].h-node[node[i].r].h;//按比例分配高度
//画横线
pr2(x+node[node[i].l].h,y,node[i].k);
p(x,y,node[i].l);
p(x+node[node[i].l].h,y,node[i].r);
}
else
{
ans[x][y]=node[i].c;//在窗口左上角填入字母
}
return ;
}
在按比例计算宽度和高度的时候,由于要将第一部分的宽度和高度向上取整,也可以先计算右子树的宽度或高度,再用总宽度或高度减去它计算出左子树的宽度或高度。
5、输出最后的图形:
void p1()//输出窗口
{
int i,j;
for(i=;i<=node[].h;i++)
{
for(j=;j<=node[].k;j++)
{
printf("%c",ans[i][j]);
}
printf("\n");
}
}
6、主函数:
#include<stdio.h>
#include<iostream>
#define N 2000
#define MAX(x,y) (((x)>(y))?(x):(y))
using namespace std;
int main()
{
int t,i,j,cas=;
cin>>t;
while(t--)
{
getchar();
k=;
chuli();//输入
//cout<<"!!"<<endl;
f();//计算窗口大小
//画外框
ans[][]='*';
for(j=;j<node[].k;j++) ans[][j]='-';
ans[][j]='*';
for(i=;i<node[].h;i++)
{
ans[i][]='|';
for(j=;j<node[].k;j++) ans[i][j]=' ';
ans[i][j]='|';
}
ans[i][]='*';
for(j=;j<node[].k;j++) ans[i][j]='-';
ans[i][j]='*';
cout<<cas++<<endl;
p(,,);//处理整个框
p1();//输出
}
}
【解题报告】POJ-1108 Split Windows的更多相关文章
- POJ1108_Split Windows 解题报告
Split Windows 题目链接:http://poj.org/problem?id=1108 题目大意: 给你一棵二叉树的先序遍历,有三种字符:|.-.A~Z,然后用窗口表示出来,|: 表示将当 ...
- POJ 1001 解题报告 高精度大整数乘法模版
题目是POJ1001 Exponentiation 虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于 ...
- POJ 2002 Squares 解题报告(哈希 开放寻址 & 链式)
经典好题. 题意是要我们找出所有的正方形.1000点,只有枚举咯. 如图,如果我们知道了正方形A,B的坐标,便可以推测出C,D两点的坐标.反之,遍历所有点作为A,B点,看C,D点是否存在.存在的话正方 ...
- Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)
http://blog.csdn.net/geniusluzh/article/details/6619575 在说Tarjan算法解决桥和边双连通分量问题之前我们先来回顾一下Tarjan算法是如何 ...
- 【九度OJ】题目1108:堆栈的使用 解题报告
[九度OJ]题目1108:堆栈的使用 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1108 题目描述: 堆栈是一种基本的数据结构.堆 ...
- 【LeetCode】659. Split Array into Consecutive Subsequences 解题报告(Python)
[LeetCode]659. Split Array into Consecutive Subsequences 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id ...
- POJ 3126 Prime Path 解题报告(BFS & 双向BFS)
题目大意:给定一个4位素数,一个目标4位素数.每次变换一位,保证变换后依然是素数,求变换到目标素数的最小步数. 解题报告:直接用最短路. 枚举1000-10000所有素数,如果素数A交换一位可以得到素 ...
- poj分类解题报告索引
图论 图论解题报告索引 DFS poj1321 - 棋盘问题 poj1416 - Shredding Company poj2676 - Sudoku poj2488 - A Knight's Jou ...
- POJ 2054 Color a Tree解题报告
题干 Bob is very interested in the data structure of a tree. A tree is a directed graph in which a spe ...
随机推荐
- C# 语音识别(文字to语音、语音to文字)
最近打算研究一下语音识别,但是发现网上很少有C#的完整代码,就把自己的学习心得放上来,和大家分享一下. 下载API: 1)SpeechSDK51.exe (67.0 ...
- ExtJs之Ext.each
<!DOCTYPE html> <html> <head> <title>ExtJs</title> <meta http-equiv ...
- OleDbType.Decimal在插入DB2后会默认赋值0.00,改为OleDbType.Double则正常
private void InsertShopClaimsTarget(ContinueTargetData.RT_SHOPCLAIMSTARGETRow aRow) { StringBuilder ...
- CKEditor上传图片—配置CKFinder
参考:http://blog.csdn.net/gavin710/article/details/8741738
- Spring学习总结(1)——Spring AOP的概念理解
1.我所知道的aop 初看aop,上来就是一大堆术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等.一下子让你不知所措,心想着:怪不得 很多人都和我说aop多难多难 .当我看进去 ...
- Junit单元测试学习笔记一
我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的.但是,我们同时应该确保每一个函数 ...
- java多线程理解2
1. 什么时候必须同步?什么叫同步?如何同步? 要跨线程维护正确的可见性,只要在几个线程之间共享非 final 变量,就必须使用 synchronized(或 volatile)以确保一个线程可以看见 ...
- ThreadLocal的几种误区
最近由于需要用到ThreadLocal,在网上搜索了一些相关资料,发现对ThreadLocal经常会有下面几种误解 一.ThreadLocal是java线程的一个实现 ThreadLoca ...
- 唯一区别是不会去取emptyText 的值,没有选选择选项的时候返回是空字符串
combox取值以及赋值的方法 function getValue() { //注意:以下这两种取值方法都会存在一个问题: 当combox设置成能输入并有只能提示的时候,当输入的不是备选项时,或到的v ...
- javascript 中文数字阿拉伯数字转换类 Nzh
之前工作中碰到了数字转中文的情景,网上找的现成方法或多或少不合我的口味,最后还是自已写了一个. 现在整理了一下,补充了繁体,自定义字符,以及反函数(中文数字转阿拉伯数字) 现在发布出来,希望能合大家的 ...