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

解法:这题既可以用来提升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. error-2015-9-9

    类型的建键部分无效,该键的所有部分均不可为null 映射从第行开始的片段时有问题 表的键具有潜在运行时冲突 列映射到概念端的属性 但是它们未形成entitySet的键属性 报错: 未能加载文件或程序集 ...

  2. Python“Non-ASCII character 'xe5' in file”报错问题(转)

    今天在编译一个Python程序的时候,一直出现"Non-ASCII character 'xe5' in file"报错问题 SyntaxError: Non-ASCII char ...

  3. EhCache RMI 分布式缓存/缓存集群

    EhCache 系统简介 EhCache 是一个纯 Java 的进程内缓存框架,具有快速.精干等特点. EhCache 的主要特性有: 快速.精干 简单: 多种缓存策略: 缓存数据有两级:内存和磁盘, ...

  4. Android-MediaRecorder-音频录制-警告-W/MediaRecorder(13811): mediarecorder went away with unhandled events

    Android-MediaRecorder-音频录制-警告-W/MediaRecorder(13811): mediarecorder went away with unhandled events ...

  5. 使用OPENROWSET、Microsoft.ACE.OLEDB实现大数据量的高效导入

    首先说明使用的环境是:java和Sqlserver. 最近公司需要进行大数据量的导入操作.原来使用的是Apache POI,虽然可以实现功能,但是因为逻辑处理中需要进行许多校验,处理速度太慢,使用多线 ...

  6. 【转】+【举例】ArcGIS中的坐标系统定义与投影转换

    背景知识: UTM (Universal Transverse Mercator)坐标系是由美国军方在1947提出的.虽然我们仍然将其看作与"高斯-克吕格"相似的坐标系统,但实际上 ...

  7. 选择流程—— switch if else结构

    一.switch switch(表达式){ case 常量1: 语句; break; case 常量2: 语句; break; … default; 语句; } 例题:运用switch结构实现购物管理 ...

  8. 2-6 Working with Lambdas

    在C++中使用匿名函数,格式如下:[] () {}; Using a Lambda to Print array Values #include <algorithm> #include ...

  9. 使用odoo价格表[pricelist]对价格进行特别处理,如 .99

    问题1, 销售价格 自动设置为 9.99 问题2, 将销售价格从 10.5 设置为 10.00 这些都可以用 priceList 实现,具体实现如下 首先,启用 priceList 在 价格表项目 有 ...

  10. 进阶版css的点滴

    -moz-:firefox: -webkit- Safari 和 Chrome