【解题报告】BZOJ2550: [Ctsc2004]公式编辑器
题意:给定一个可视化计算器的操作序列,包括插入数字、字母、运算符、分数、矩阵以及移动光标、矩阵插入行、插入列,输出操作序列结束后的屏显(数学输出)。
解法:这题既可以用来提升OI/ACM写大代码模拟题的能力,也可以作为一道不错的C++多态性练习题来写。用二维字符数组buffer进行输出记录,用一个基类Drawable表示屏显元素,以及Character(单个字符)、Sequence(输入框序列)、Fraction(分数)、Matrix(矩阵)派生类。主要虚函数包括:
virtual void draw(int ix, int iy); //表示以(x,y)为左上点绘制这个Drawable;
virtual bool insert(Drawable *obj); //表示尝试在当前指针上插入obj;
virtual void calSize(); //计算当前obj的长宽以及对齐行;
virtual ~Drawable(){}; //虽然是OI题,但是由于有动态内存声明,最好有重载虚构函数释放内存的部分。
然后就是大模拟。注意题意即可。
代码:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
#define rep(i,n) for(int i=1;i<=(n);++i)
#define rep2(i,a,b) for(int i=(a);i<=(b);++i)
char buffer[][];
enum Direction
{
UP = ,
DOWN = ,
LEFT = ,
RIGHT =
};
class Drawable
{
protected:
int width, height;
int centerX;
Drawable *parent;
public:
Drawable(Drawable *par = )
{
parent = par;
}
virtual ~Drawable(){}
virtual void calSize() = ;
virtual void draw(int ix, int iy) = ;
virtual bool moveDir(Direction id) = ;
virtual bool leftMost() = ;
virtual bool rightMost() = ;
virtual bool moveHome() = ;
virtual bool moveEnd() = ;
virtual bool insert(Drawable *obj) = ;
virtual bool addRow() = ;
virtual bool addCol() = ;
inline int getHeight()
{
return height;
}
inline int getWidth()
{
return width;
}
inline int getUpperHeight()
{
return centerX - ;
}
inline int getLowerHeight()
{
return height - centerX;
}
inline Drawable *getParent()
{
return parent;
}
inline void setParent(Drawable *par)
{
parent = par;
}
};
class Character :public Drawable
{
private:
char c;
public:
Character(Drawable *par) :Drawable(par)
{
c = ;
}
Character(char ic, Drawable *par) :Drawable(par)
{
c = ic;
}
virtual ~Character(){}
virtual void calSize()
{
height = ; centerX = ;
width = c == ? : c == '-' ? : ;
}
virtual bool moveDir(Direction id){ return false; }
virtual bool leftMost(){ return false; }
virtual bool rightMost(){ return false; }
virtual bool moveHome(){ return false; }
virtual bool moveEnd(){ return false; }
virtual bool insert(Drawable *obj){ return false; }
virtual bool addRow(){ return false; }
virtual bool addCol(){ return false; }
virtual void draw(int ix, int iy)
{
if (c == )return;
if (c == '-')
{
buffer[ix][iy] = buffer[ix][iy + ] = ' ';
buffer[ix][iy + ] = c;
}
else buffer[ix][iy] = c;
}
};
class Sequence :public Drawable
{
private:
vector<Drawable*> list;
int cursor;
bool cursorInside;
bool insideCursor(Direction);
bool outsideCursor(Direction);
public:
Sequence(Drawable* par) :Drawable(par)
{
cursor = ;
cursorInside = false;
}
virtual ~Sequence()
{
rep2(i, , (int)list.size() - )
{
delete list[i];
}
}
virtual void calSize()
{
width = ;
int upsize = , lowsize = ;
rep2(i, , (int)list.size() - )
{
list[i]->calSize();
width += list[i]->getWidth();
upsize = max(upsize, list[i]->getUpperHeight());
lowsize = max(lowsize, list[i]->getLowerHeight());
}
height = upsize + lowsize + ;
centerX = upsize + ;
}
virtual bool moveDir(Direction id)
{
return (insideCursor(id) || outsideCursor(id));
}
virtual bool leftMost()
{
cursor = ;
cursorInside = false;
return true;
}
virtual bool rightMost()
{
cursor = list.size();
cursorInside = false;
return true;
}
virtual bool moveHome()
{
if (cursorInside)return list[cursor]->moveHome();
return leftMost();
}
virtual bool moveEnd()
{
if (cursorInside)return list[cursor]->moveEnd();
return rightMost();
}
virtual bool insert(Drawable *obj)
{
if (cursorInside)return list[cursor]->insert(obj);
list.insert(list.begin() + cursor, obj);
moveDir(RIGHT);
obj->setParent(this);
return true;
}
virtual void draw(int ix, int iy)
{
int tx = ix + centerX - ;
int ty = iy;
rep2(i, , (int)list.size() - )
{
list[i]->draw(tx - list[i]->getUpperHeight(), ty);
ty += list[i]->getWidth();
}
}
virtual bool addRow()
{
if (cursorInside)return list[cursor]->addRow();
return false;
}
virtual bool addCol()
{
if (cursorInside)return list[cursor]->addCol();
return false;
}
};
class Fraction :public Drawable
{
private:
Drawable *u, *d;
bool cursorUp;
public:
Fraction(Drawable *par) :Drawable(par)
{
u = new Sequence(this);
d = new Sequence(this);
cursorUp = true;
}
virtual ~Fraction()
{
delete u;
delete d;
}
virtual void calSize()
{
u->calSize();
d->calSize();
width = max(u->getWidth(), d->getWidth()) + ;
height = u->getHeight() + d->getHeight() + ;
centerX = u->getHeight() + ;
}
virtual bool moveDir(Direction id)
{
if (cursorUp)
{
if (u->moveDir(id))return true;
if (id == DOWN)
{
cursorUp = false;
return d->leftMost();
}
}
else
{
if (d->moveDir(id))return true;
if (id == UP)
{
cursorUp = true;
return u->leftMost();
}
}
return false;
}
virtual bool leftMost()
{
cursorUp = true;
return u->leftMost();
}
virtual bool rightMost()
{
cursorUp = true;
return u->rightMost();
}
virtual bool moveHome()
{
return cursorUp ? u->moveHome() : d->moveHome();
}
virtual bool moveEnd()
{
return cursorUp ? u->moveEnd() : d->moveEnd();
}
virtual bool insert(Drawable *obj)
{
return cursorUp ? u->insert(obj) : d->insert(obj);
}
virtual void draw(int ix, int iy)
{
rep(j, width)
{
buffer[ix + centerX - ][iy + j - ] = '-';
}
u->draw(ix, iy + (width - u->getWidth()) / );
d->draw(ix + centerX, iy + (width - d->getWidth()) / );
}
virtual bool addRow()
{
return cursorUp ? u->addRow() : d->addRow();
}
virtual bool addCol()
{
return cursorUp ? u->addCol() : d->addCol();
}
};
class Matrix :public Drawable
{
private:
vector< vector<Drawable *> >grid;
int nx, ny;
vector<int> upSize, downSize, colSize;
int cursorX, cursorY;
public:
Matrix(Drawable *par) :Drawable(par)
{
vector<Drawable*> tmp;
tmp.push_back(new Sequence(this));
grid.push_back(tmp);
nx = ny = ;
}
virtual ~Matrix()
{
rep2(i, , nx-)
{
rep2(j, , ny-)
{
delete grid[i][j];
}
}
}
virtual void calSize()
{
upSize.clear();
downSize.clear();
colSize.clear();
upSize.resize(nx);
downSize.resize(nx);
colSize.resize(ny);
height = nx - ; width = ny + ;
rep2(i, , nx - )
{
rep2(j, , ny - )
{
grid[i][j]->calSize();
upSize[i] = max(upSize[i], grid[i][j]->getUpperHeight());
downSize[i] = max(downSize[i], grid[i][j]->getLowerHeight());
colSize[j] = max(colSize[j], grid[i][j]->getWidth());
}
}
rep2(i, , nx - )height += upSize[i] + downSize[i] + ;
rep2(j, , ny - )width += colSize[j];
if (nx % )
{
centerX = nx / + + upSize[nx / ];
rep2(i, , nx / - )
{
centerX += upSize[i] + downSize[i] + ;
}
}
else
{
centerX = nx / ;
rep2(i, , nx / - )
{
centerX += upSize[i] + downSize[i] + ;
}
}
}
virtual bool moveDir(Direction id)
{
if (grid[cursorX][cursorY]->moveDir(id))return true;
if (id == UP)
{
if (cursorX > )return grid[--cursorX][cursorY]->leftMost();
}
else if (id == DOWN)
{
if (cursorX < nx - )return grid[++cursorX][cursorY]->leftMost();
}
else if (id == LEFT)
{
if (cursorY > )return grid[cursorX][--cursorY]->rightMost();
}
else if (id == RIGHT)
{
if (cursorY < ny - )return grid[cursorX][++cursorY]->leftMost();
}
return false;
}
virtual bool leftMost()
{
return grid[cursorX = (nx - ) / ][cursorY = ]->leftMost();
}
virtual bool rightMost()
{
return grid[cursorX = (nx - ) / ][cursorY = ny - ]->rightMost();
}
virtual bool moveHome()
{
return grid[cursorX][cursorY]->moveHome();
}
virtual bool moveEnd()
{
return grid[cursorX][cursorY]->moveEnd();
}
virtual bool insert(Drawable *obj)
{
return grid[cursorX][cursorY]->insert(obj);
}
virtual void draw(int ix, int iy)
{
int tx = ix;
rep2(i, , nx - )
{
tx += upSize[i];
int ty = iy + ;
buffer[tx][ty - ] = '[';
rep2(j, , ny - )
{
grid[i][j]->draw(tx - grid[i][j]->getUpperHeight(), ty + (colSize[j] - grid[i][j]->getWidth()) / );
ty += colSize[j] + ;
}
buffer[tx][ty - ] = ']';
tx += downSize[i] + ;
}
}
virtual bool addCol()
{
if (grid[cursorX][cursorY]->addCol())return true;
++ny;
rep2(i, , nx - )
{
grid[i].insert(grid[i].begin() + cursorY, new Sequence(this));
}
return true;
}
virtual bool addRow()
{
if (grid[cursorX][cursorY]->addRow())return true;
++nx;
vector<Drawable*> tmp;
rep2(j, , ny - )
{
tmp.push_back(new Sequence(this));
}
grid.insert(grid.begin() + cursorX, tmp);
return true;
}
};
bool Sequence::insideCursor(Direction id)
{
if (cursorInside)
{
if (list[cursor]->moveDir(id))return true;
if (id == LEFT)
{
cursorInside = false;
return true;
}
else if (id == RIGHT)
{
cursorInside = false;
++cursor;
return true;
}
}
return false;
}
bool Sequence::outsideCursor(Direction id)
{
if (!cursorInside)
{
if (id == LEFT&&cursor>)
{
if (list[cursor - ]->rightMost())
{
--cursor;
cursorInside = true;
}
else
{
--cursor;
}
return true;
}
else if (id == RIGHT&&cursor<(int)list.size())
{
if (list[cursor]->leftMost())
{
cursorInside = true;
}
else
{
++cursor;
}
return true;
}
}
return false;
}
class Scanner
{
private:
Sequence root;
public:
Scanner() :root()
{ }
void init()
{
memset(buffer, ' ', sizeof buffer);
}
bool scan()
{
char input[];
if (!(cin >> input))return false;
if (strcmp(input, "Fraction") == )
root.insert(new Fraction());
else if (strcmp(input, "Matrix") == )
root.insert(new Matrix());
else if (strcmp(input, "AddRow") == )
root.addRow();
else if (strcmp(input, "AddCol") == )
root.addCol();
else if (strcmp(input, "Right") == )
root.moveDir(RIGHT);
else if (strcmp(input, "Left") == )
root.moveDir(LEFT);
else if (strcmp(input, "Up") == )
root.moveDir(UP);
else if (strcmp(input, "Down") == )
root.moveDir(DOWN);
else if (strcmp(input, "Home") == )
root.moveHome();
else if (strcmp(input, "End") == )
root.moveEnd();
else
root.insert(new Character(input[], )); return true;
}
void print()
{
root.calSize();
root.draw(, );
int nx = root.getHeight(), ny = root.getWidth();
int ty;
rep2(ix, , nx - )
{
for (ty = ny; ty >= ; --ty)if (buffer[ix][ty] != ' ')break;
rep2(iy, , ty)putchar(buffer[ix][iy]);
putchar('\n');
}
}
}scanner; int main()
{
scanner.init();
while (scanner.scan());
scanner.print();
return ;
}
转载请注明出处:http://www.cnblogs.com/instr3/p/4803663.html
【解题报告】BZOJ2550: [Ctsc2004]公式编辑器的更多相关文章
- 【百度之星2014~初赛(第二轮)解题报告】Chess
声明 笔者近期意外的发现 笔者的个人站点http://tiankonguse.com/ 的非常多文章被其他站点转载.可是转载时未声明文章来源或參考自 http://tiankonguse.com/ 站 ...
- poj1173 解题报告
poj1173 解题报告2013-07-21 13:31 by 期待 ., 42 阅读, 0 评论, 收藏, 编辑 http://poj.org/problem?id=1173 发现此题资料甚少,斗胆 ...
- 【百度之星2014~初赛(第二轮)解题报告】JZP Set
声明 笔者近期意外的发现 笔者的个人站点http://tiankonguse.com/ 的非常多文章被其他站点转载,可是转载时未声明文章来源或參考自 http://tiankonguse.com/ 站 ...
- $HNOI\ 2010$ 解题报告
HNOI 2010 解题报告 0. HNOI2010 AC代码包下载地址 注: 戳上面的标题中的'地址' 下载 代码包, 戳下面每一题的文件名 可进入 题目链接. 每一题 对应代码的文件名 我在 每一 ...
- CYJian的水题大赛2 解题报告
这场比赛是前几天洛谷上 暮雪﹃紛紛dalao的个人公开赛,当时基本上都在水暴力分......也没有好好写正解(可能除了T1) 过了几天颓废的日子之后,本蒟蒻觉得应该卓越一下了qwq,所以就打算写一个解 ...
- 2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告
2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh ...
- 解题报告 之 HDU5288 OO' s Sequence
解题报告 之 HDU5288 OO' s Sequence Description OO has got a array A of size n ,defined a function f(l,r) ...
- zoj 2313 Chinese Girls' Amusement 解题报告
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1313 题目意思:有 N 个人(编号依次为1~N)围成一个圆圈,要求求 ...
- HDU-1576 A/B 基础数论+解题报告
HDU-1576 A/B 基础数论+解题报告 题意 求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973) (我们给定的A必能被B整除,且gcd(B,9973) = 1). 输入 数据 ...
随机推荐
- spring mvc 第三天【注解实现springmvc Handler返回值为Object 的配置】
这里使用的是在前台发起请求Handler,后台伪造数据响应给前台, 解决方案:将之前的viewResolver抹掉,配置对应(request)请求的Handler信息如下 之前Handler返回的都直 ...
- 更改XAMPP中MySQL数据库的端口号
更改XAMPP中MySQL数据库的端口号 如果电脑上已安装MySql数据库,还想用XAMPP中自带的数据库就需要更改XAMPP中数据库的端口号,避免和已安装的数据库冲突.本例以更改为3307端口号为例 ...
- Camstar Portal modeling user guid --设置本地时间
登陆--studio --portal settings -- timezone settings 里面有EST 和EDT两个时间. 现在要设置为北京时间(08:00) 原文: Localizatio ...
- MySQL查询今天/本周/上周/本月/上个月份的数据
MySQL查询的方式很多,下面为您介绍的MySQL查询实现的是查询本周.上周.本月.上个月份的数据,如果您对MySQL查询方面感兴趣的话,不妨一看. 查询当前今天的数据 SELECT name,sub ...
- Android版本4.0~7.0
Android 4.0 Ice Cream Sandwich(冰激凌三明治):2011年10月19日发布 版本主要更新如下:全新的UI:全新的Chrome Lite浏览器:截图功能:更强大的图片编辑功 ...
- Window Server 2012 R2 没有照片查看器 打开图片都是画板问题怎么解决
新安装了 Window Server 2012 R2 系统,感觉屌屌的样子,加上开机速度蛮快,心里略爽.结果,打开图片一看,发现竟然是画板,而且还没有照片查看器,顿时泪流满面. 后来我利用了强大的百度 ...
- easyui 使用问题积累
一.<a>标签中onclick和javascript事件与grid的select事件执行的先后顺序 html: <a href='javascript:func();' onclic ...
- MySQL基础(三)
数据插入 INSERT是用来插入行到数据库表的 ## 给出插入数据的字段名称,使得数据插入不依赖表中列名称的定义顺序 INSERT INTO customers(cust_name,cust_addr ...
- PHP获取页面执行时间的方法
一些循环代码,有时候要知道页面执行的时间,可以添加以下几行代码到页面头部和尾部: 头部: <?php $stime=microtime(true); 尾部: $etime=microtime(t ...
- 关于openssl几个API的一点小收获
今天心血来潮突然想搞搞openssl了,趁着端午小假,刚好有空可以鼓捣孤岛自己喜欢的东西,出去东奔西跑的实在太造孽了,还是宅起来给自己充充电吧.下载openssl最新代码1.0.1g,修复了" ...