题意:给定一个可视化计算器的操作序列,包括插入数字、字母、运算符、分数、矩阵以及移动光标、矩阵插入行、插入列,输出操作序列结束后的屏显(数学输出)。

解法:这题既可以用来提升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]公式编辑器的更多相关文章

  1. 【百度之星2014~初赛(第二轮)解题报告】Chess

    声明 笔者近期意外的发现 笔者的个人站点http://tiankonguse.com/ 的非常多文章被其他站点转载.可是转载时未声明文章来源或參考自 http://tiankonguse.com/ 站 ...

  2. poj1173 解题报告

    poj1173 解题报告2013-07-21 13:31 by 期待 ., 42 阅读, 0 评论, 收藏, 编辑 http://poj.org/problem?id=1173 发现此题资料甚少,斗胆 ...

  3. 【百度之星2014~初赛(第二轮)解题报告】JZP Set

    声明 笔者近期意外的发现 笔者的个人站点http://tiankonguse.com/ 的非常多文章被其他站点转载,可是转载时未声明文章来源或參考自 http://tiankonguse.com/ 站 ...

  4. $HNOI\ 2010$ 解题报告

    HNOI 2010 解题报告 0. HNOI2010 AC代码包下载地址 注: 戳上面的标题中的'地址' 下载 代码包, 戳下面每一题的文件名 可进入 题目链接. 每一题 对应代码的文件名 我在 每一 ...

  5. CYJian的水题大赛2 解题报告

    这场比赛是前几天洛谷上 暮雪﹃紛紛dalao的个人公开赛,当时基本上都在水暴力分......也没有好好写正解(可能除了T1) 过了几天颓废的日子之后,本蒟蒻觉得应该卓越一下了qwq,所以就打算写一个解 ...

  6. 2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告

    2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh ...

  7. 解题报告 之 HDU5288 OO&#39; s Sequence

    解题报告 之 HDU5288 OO' s Sequence Description OO has got a array A of size n ,defined a function f(l,r) ...

  8. zoj 2313 Chinese Girls' Amusement 解题报告

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1313 题目意思:有 N 个人(编号依次为1~N)围成一个圆圈,要求求 ...

  9. HDU-1576 A/B 基础数论+解题报告

    HDU-1576 A/B 基础数论+解题报告 题意 求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973) (我们给定的A必能被B整除,且gcd(B,9973) = 1). 输入 数据 ...

随机推荐

  1. Odoo 中的 Controller

    来自  Odoo处理HTTP请求的接口用的Contoller类,封装于web模块中. --------------------------------------------------------- ...

  2. PL/SQL EO 设计与开发

    1.INSERT 调用PL/SQL 去insert的时候,没有使用super(),此时应当自己创建callable statement: 调用checkErrors()方法在执行 callable s ...

  3. nw_socket_handle_socket_event解决

    http://www.bkjia.com/IOSjc/1158465.html 出现问题如下 to a parent directory scheduled for deletion nw_endpo ...

  4. oracle分页查询sql

    select * from( select shopid,rownum rn from p_shopinfo where is_hot=1 and rownum <=6 order by sho ...

  5. mysql计划字段中有多少个逗号,或者某个标识符

    eg:计划url中有多少个小数点 select length('www.mysql.com')-length(REPLACE('www.mysql.com','.',''));

  6. redis——持久化篇

    众所周知,redis是内存数据库,它把数据存储在内存中,这样在加快读取速度的同时也对数据安全性产生了新的问题,即当redis所在服务器发生宕机后,redis数据库里的所有数据将会全部丢失. 为了解决这 ...

  7. NGUI 灰化按钮或图标

    在游戏中某些地方可能需要对按钮进行灰化显示,从而表示不能点击!在网上找了一下有些方法是直接用UITexture+灰化shader去做这件事!另外有些方案写的不太清楚,看不懂!不过也基本都是要使用灰化s ...

  8. 嗯,开通blog了!

    应老师建议,开通博客,“把学习时遇到的疑惑和问题随时用blog记录下来”,“把前期的学习心得写上,有时间最好把自己的学习计划也写上”. 用博客记录自己Linux和其他技术的学习日记,记录下学习实践中遇 ...

  9. 在ubuntu16编译安装nginx-1.10.2(full)完全自带组件

    第一步:先安装全部用到的包 apt install gcc libpcre++-dev libssl-dev make \ libxml2-dev libxslt-dev libgd-dev libg ...

  10. Oracle Cursor

    1.概念 游标:从字面来理解就是游动的光标.用数据库语言来描述,游标是映射在结果集中一行数据上的位置实体,有了游标,用户就可以访问结果集中的任意一行数据了.将游标放置到某行后,即可对该行数据进行操作, ...