1 条题解

  • 0
    @ 2025-4-8 20:51:30

    Description

    The Japan company you are working for produce plotter devices that can draw nice pictures. To support customers who do not posses the special hardware, you were asked to write an emulation driver that simulates the work of the plotter and prints the picture on a computer screen.

    The plotter is driven with a simple language consisting of several drawing commands:

    POINT x y -- makes a little circle at the given coordinates. TEXT x y txt -- displays a line of text at the given coordinates. LINE x1 y1 x2 y2 -- draws a line between the specified points. CLEAR x1 y1 x2 y2 -- erases the given rectangle. PRINT -- prints an output page and terminates the current job. The emulation driver uses few ASCII characters to represent the picture, one character being a basic unit of the coordinate system. The top-left character has coordinates (1,1). The X-axis aims to the right, the Y-axis goes down.

    The particular commands are emulated as follows:

    POINT: The driver puts a lowercase letter "o" at the given coordinates. TEXT: Shows a single line of text, the first character is positioned at the given coordinates and the text always goes right. LINE: Simulates a straight line between two points. The line is formed by one of the following characters: dash ("-"), pipe ("|"), slash ("/"), or backslash (""), according to its direction. CLEAR: The driver fills the appropriate rectangular area with spaces, including the bounding rows and columns. PRINT: This command causes the driver to print the picture surrounded with a nice frame made of plus ("+"), minus ("-"), and pipe ("|") characters. If more objects should be drawn across a single character, the following rules apply:

    If the same character is drawn several times, it is used without a change. If only pipe and minus characters are involved, they result in the plus sign ("+"). If only slashes and backslashes are involved, the result is the lowercase letter "x". Otherwise, the asterisk ("*") is displayed. Before a script is given to the driver, it is checked by a special preprocessor, which rejects all invalid commands. Therefore, you may assume that all coordinates are within the range of the page. Also, with the LINE command, the two points are always different and the line is strictly either vertical, horizontal, or at the angle of 45o to the axes. There is no assumption on the relative position of the points used with the LINE and CLEAR commands. The text in the TEXT command is always composed only of uppercase letter and digits.

    Input

    The input consists of several scripts. Each script begins with a line containing two integers X and Y, separated with space, 1 <= X, Y <= 75. These numbers specify the dimensions of the page. Every other line contains exactly one of the above commands. The commands are always uppercase, command arguments are separated with one space.

    The PRINT command is always the last command of the script. After the PRINT command, a new script begins. The input is terminated with two zeros, which are not considered to be a script.

    Output

    For each script, output the emulated picture, created as specified above. After the picture, print one blank line.

    示例输入 1

    20 10 LINE 3 2 11 10 LINE 3 10 11 2 LINE 20 3 8 3 TEXT 6 8 TEST LINE 19 1 19 10 LINE 17 10 17 1 LINE 16 1 16 10 LINE 13 6 20 6 CLEAR 20 5 15 7 LINE 18 1 18 10 TEXT 12 10 NICEPICTURE POINT 1 1 POINT 3 2 PRINT 1 1 POINT 1 1 CLEAR 1 1 1 1 PRINT 3 3 LINE 2 1 2 3 LINE 1 2 3 2 LINE 2 3 2 1 LINE 3 2 1 2 LINE 2 1 2 3 LINE 1 2 3 2 PRINT 0 0

    示例输出 1

    +--------------------+ |o |||| | | * / |||| | | \ -------++++-| | \ / |||| | | \ / | | | x -- | | | / \ | | | /TES |||| | | / \ |||| | | / \NICE****U| +--------------------+

    +-+ | | +-+

    +---+ | | | |-+-| | | | +---+

    Source CTU Open 2004

    题目描述

    你所在的一家日本公司生产能够绘制精美图片的绘图仪设备。为了支持那些没有这种特殊硬件的客户,你被要求编写一个模拟驱动程序,模拟绘图仪的工作并在计算机屏幕上打印图片。

    绘图仪由几种简单的绘图命令驱动:

    • POINT x y:在给定坐标处绘制一个小圆圈。
    • TEXT x y txt:在给定坐标处显示一行文本。
    • LINE x1 y1 x2 y2:在指定的两点之间绘制一条直线。
    • CLEAR x1 y1 x2 y2:清除给定的矩形区域。
    • PRINT:打印输出页面并终止当前任务。

    模拟驱动程序使用ASCII字符来表示图片,每个字符代表坐标系中的一个基本单位。左上角字符的坐标为(1,1)。X轴向右延伸,Y轴向下延伸。

    命令模拟方式

    • POINT:在给定坐标处放置小写字母"o"。
    • TEXT:显示单行文本,第一个字符位于给定坐标,文本始终向右延伸。
    • LINE:模拟两点之间的直线,根据方向使用字符:横线("-")、竖线("|")、斜线("/")或反斜线("")。
    • CLEAR:用空格填充指定的矩形区域,包括边界行和列。
    • PRINT:打印图片,并用加号("+")、减号("-")和竖线("|")组成的边框包围。

    重叠字符规则

    • 如果同一字符被多次绘制,保持不变。
    • 如果只有竖线和横线重叠,结果为加号("+")。
    • 如果只有斜线和反斜线重叠,结果为小写字母"x"。
    • 其他情况显示星号("*")。

    输入说明

    输入包含多个脚本。每个脚本以两个整数X和Y开始,表示页面的尺寸。接下来的每一行包含一个命令。命令总是大写,参数之间用一个空格分隔。PRINT命令总是脚本的最后一条命令。输入以两个0结束。

    输出说明

    对于每个脚本,输出模拟的图片,按照上述规则生成。每个图片后输出一个空行。

    示例输入 1

    20 10
    LINE 3 2 11 10
    LINE 3 10 11 2
    LINE 20 3 8 3
    TEXT 6 8 TEST
    LINE 19 1 19 10
    LINE 17 10 17 1
    LINE 16 1 16 10
    LINE 13 6 20 6
    CLEAR 20 5 15 7
    LINE 18 1 18 10
    TEXT 12 10 NICEPICTURE
    POINT 1 1
    POINT 3 2
    PRINT
    1 1
    POINT 1 1
    CLEAR 1 1 1 1
    PRINT
    3 3
    LINE 2 1 2 3
    LINE 1 2 3 2
    LINE 2 3 2 1
    LINE 3 2 1 2
    LINE 2 1 2 3
    LINE 1 2 3 2
    PRINT
    0 0
    

    示例输出 1

    +--------------------+
    |o              |||| |
    |  *       /    |||| |
    |   \   --*-----++++-|
    |    \   /      |||| |
    |     \ /         |  |
    |      x     --   |  |
    |     / \         |  |
    |    /TES*      |||| |
    |   /     \     |||| |
    |  /       \NICE****U|
    +--------------------+
    
    +-+
    | |
    +-+
    
    +---+
    | | |
    |-+-|
    | | |
    +---+
    

    算法标签

    模拟算法,字符串处理,二维数组

    题意分析

    本题描述了一个绘图仪仿真驱动程序的功能需求,要在电脑屏幕上模拟绘图仪的工作,根据一系列特定的绘图命令来绘制图形并输出结果。具体信息如下: 输入: 由多个脚本构成,每个脚本开头是两个整数 X 和 Y(1 <= X, Y <= 75),用来指定页面的尺寸。 随后的每行包含一个绘图命令,命令总是大写,命令参数用一个空格分隔。 命令有 POINT x y、TEXT x y txt、LINE x1 y1 x2 y2、CLEAR x1 y1 x2 y2 和 PRINT。 PRINT 命令是每个脚本的最后一个命令,输入以 0 0 结束。 输出: 对于每个脚本,输出模拟绘制的图形,图形用 ASCII 字符表示,并且图形周围有由 +、- 和 | 构成的边框。 每个图形输出后打印一个空行。 绘图规则: POINT:在指定坐标处放置小写字母 o。 TEXT:在指定坐标处显示一行文本,文本向右显示。 LINE:根据直线方向用 -、|、/ 或 \ 绘制直线。 CLEAR:用空格填充指定的矩形区域。 PRINT:打印带有边框的图形。 字符重叠规则: 若多次绘制相同字符,字符保持不变。 若只涉及 - 和 |,结果为 +。 若只涉及 / 和 \,结果为 x。 其他情况显示 *。

    解题思路

    为实现该仿真驱动程序,可以按照以下步骤进行: 初始化:读取页面的尺寸 X 和 Y,创建一个二维字符数组来表示页面,初始时所有字符设为空格。 命令处理: 循环读取命令,根据命令类型执行相应操作。 对于 POINT 命令,在指定坐标处放置 o。 对于 TEXT 命令,在指定坐标处开始显示文本。 对于 LINE 命令,根据直线方向用相应字符绘制直线。 对于 CLEAR 命令,用空格填充指定矩形区域。 对于 PRINT 命令,打印带有边框的图形,然后结束当前脚本的处理。 字符重叠处理:在绘制图形时,若多个对象绘制到同一字符位置,按照字符重叠规则更新该位置的字符。 结束条件:当输入为 0 0 时,结束程序。 算法标签 模拟算法:本题主要是对绘图仪工作过程进行模拟,按照输入的命令依次执行相应的绘图操作,最终输出模拟结果,属于典型的模拟算法应用。 字符串处理:需要处理输入的命令字符串,解析出命令类型和参数,这涉及到字符串的分割和比较操作。 二维数组操作:使用二维数组来表示页面,对数组中的元素进行读写和更新操作,以实现图形的绘制和清除。

    标程

    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int m, n;
    vector<vector<char> > map; // C++98 需要额外的空格 `> >`
    
    // 交换两个整数的值
    void swap(int &x, int &y) {
        int tmp = x;
        x = y;
        y = tmp;
    }
    
    // 打印地图,添加边框
    void print() {
        cout << "+";
        for (int i = 0; i < m; ++i) {
            cout << "-";
        }
        cout << "+\n";
    
        for (int i = 0; i < n; ++i) {
            cout << "|";
            for (int j = 0; j < m; ++j) {
                cout << map[i][j];
            }
            cout << "|\n";
        }
    
        cout << "+";
        for (int i = 0; i < m; ++i) {
            cout << "-";
        }
        cout << "+\n\n";
    }
    
    // 根据规则更新地图上指定位置的字符
    void fix(int x, int y, char c) {
        if (map[x][y] == c) return;
        if (map[x][y] == ' ') {
            map[x][y] = c;
        } else if ((map[x][y] == '-' || map[x][y] == '+') && c == '|') {
            map[x][y] = '+';
        } else if ((map[x][y] == '|' || map[x][y] == '+') && c == '-') {
            map[x][y] = '+';
        } else if ((map[x][y] == '\\' || map[x][y] == 'x') && c == '/') {
            map[x][y] = 'x';
        } else if ((map[x][y] == '/' || map[x][y] == 'x') && c == '\\') {
            map[x][y] = 'x';
        } else {
            map[x][y] = '*';
        }
    }
    
    // 在指定位置绘制一个点
    void point(int x, int y) {
        fix(y, x, 'o');
    }
    
    // 清除指定矩形区域的内容
    void clear(int x1, int y1, int x2, int y2) {
        if (x1 > x2) swap(x1, x2);
        if (y1 > y2) swap(y1, y2);
        for (int i = y1; i <= y2; ++i) {
            for (int j = x1; j <= x2; ++j) {
                map[i][j] = ' ';
            }
        }
    }
    
    // 在两点之间绘制一条线
    void line(int y1, int x1, int y2, int x2) {
        if (x1 == x2) {
            if (y1 > y2) swap(y1, y2);
            for (int i = y1; i <= y2; ++i) {
                fix(x1, i, '-');
            }
        } else if (y1 == y2) {
            if (x1 > x2) swap(x1, x2);
            for (int i = x1; i <= x2; ++i) {
                fix(i, y1, '|');
            }
        } else {
            if (x1 > x2) {
                swap(x1, x2);
                swap(y1, y2);
            }
            if (x1 < x2 && y1 < y2) {
                for (int i = 0; i <= x2 - x1; ++i) {
                    fix(x1 + i, y1 + i, '\\');
                }
            } else {
                for (int i = 0; i <= x2 - x1; ++i) {
                    fix(x1 + i, y1 - i, '/');
                }
            }
        }
    }
    
    // 在指定位置绘制文本
    void text(int y, int x, const string &s) {
        int l = s.length();
        for (int i = 0; i < l; ++i) {
            if (y + i >= m) break;
            fix(x, y + i, s[i]);
        }
    }
    
    int main() {
        string order;
        string tex;
        int x1, y1, x2, y2;
    
        while (cin >> m >> n && (m || n)) {
            map.assign(n, vector<char>(m, ' '));
    
            while (cin >> order) {
                if (order == "LINE") {
                    cin >> x1 >> y1 >> x2 >> y2;
                    line(x1 - 1, y1 - 1, x2 - 1, y2 - 1);
                } else if (order == "CLEAR") {
                    cin >> x1 >> y1 >> x2 >> y2;
                    clear(x1 - 1, y1 - 1, x2 - 1, y2 - 1);
                } else if (order == "POINT") {
                    cin >> x1 >> y1;
                    point(x1 - 1, y1 - 1);
                } else if (order == "TEXT") {
                    cin >> x1 >> y1 >> tex;
                    text(x1 - 1, y1 - 1, tex);
                } else {
                    print();
                    break;
                }
            }
        }
        return 0;
    }
    • 1

    信息

    ID
    1123
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者