[201512-3]ccf-csp——画图

题目内容
题目内容
输入格式
第1行有三个整数m, n和q。m和n分别表示画布的宽度和高度,以字符为单位。q表示画图操作的个数。
第2行至第q + 1行,每行是以下两种形式之一:

  • 0 x1 y1 x2 y2:表示画线段的操作,(x1, y1)和(x2, y2)分别是线段的两端,满足要么x1 = x2 且y1 ≠ y2,要么 y1 = y2 且 x1 ≠ x2。
  • 1 x y c:表示填充操作,(x, y)是起始位置,保证不会落在任何已有的线段上;c 为填充字符,是大小写字母。

画布的左下角是坐标为 (0, 0) 的位置,向右为x坐标增大的方向,向上为y坐标增大的方向。这q个操作按照数据给出的顺序依次执行。画布最初时所有位置都是字符 .(小数点)。

输出格式
输出有n行,每行m个字符,表示依次执行这q个操作后得到的画图结果。

输入示例1

4 2 3
1 0 0 B
0 1 0 2 0
1 0 0 A

输出示例1
在这里插入图片描述
输入示例2

16 13 9
0 3 1 12 1
0 12 1 12 3
0 12 3 6 3
0 6 3 6 9
0 6 9 12 9
0 12 9 12 11
0 12 11 3 11
0 3 11 3 1
1 4 2 C

输出示例2
在这里插入图片描述
评测用例规模与约定
所有的评测用例满足:2 ≤ m, n ≤ 100,0 ≤ q ≤ 100,0 ≤ x < m(x表示输入数据中所有位置的x坐标),0 ≤ y < n(y表示输入数据中所有位置的y坐标)

解题思路
看完题目之后容易发现,实际上的操作只有两种,所以对应每种操作分别写一个函数就行了。

首先是画线函数:

题目中说明了保证画的线一定是直线,不会是斜线,所以我们只需要考虑两种情况:x相同的画竖线情况,与y相同的画横线的情况。
获取起始点到终点的坐标,然后遍历画图就行了,但是这里有两个坑:

  1. 给出的x2或y2不保证一定比x1或y1大,所以这里需要人为判断一下。
  2. 画线的时候如果此时位置已经是‘ + ’了,不能修改。

然后是填色部分:

实际上填色部分就是普通的遍历,显然我们有bfs和dfs两种选择,这两种选择的中止判定都是一样的:

  1. 撞到了边界
  2. 要画的目标的颜色已经是当前的c了
  3. 撞到了画的线:‘ - ’ ‘ | ’ ‘ + ’

以下给出AC的代码,我把bfs和dfs的都写了。
实践是检验真理的唯一标准,这道题里,dfs不管是时间还是空间,都远胜于bfs…bfs甚至超时了,看官可自行取舍。
oj

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

//东北西南偏移值
const int offx[4] = { 1,0,-1,0 };
const int offy[4] = { 0,1,0,-1 };

int m, n, op;//宽度,高度和操作的个数

char map[101][101];//map[x][y]

void DrawLine(int x1, int y1, int x2, int y2)
{
    if (x1 == x2)//画竖线
    {
        if (y2 < y1)//保证y2更大
        {
            int temp = y1;
            y1 = y2;
            y2 = temp;
        }

        for (int y = y1; y <= y2; y++)
        {
            if (map[x1][y] == '+') continue;

            if (map[x1][y] == '-')
            {
                map[x1][y] = '+';
            }
            else
            {
                map[x1][y] = '|';
            }
        }
    }
    else if (y1 == y2)
    {
        if (x2 < x1)
        {
            int temp = x1;
            x1 = x2;
            x2 = temp;
        }

        for (int x = x1; x <= x2; x++)
        {
            if (map[x][y1] == '+') continue;

            if (map[x][y1] == '|')
            {
                map[x][y1] = '+';
            }
            else
            {
                map[x][y1] = '-';
            }
        }
    }
}

//这个结构体只给bfs使用
struct Point
{
    int x, y;
    Point(int x, int y) :x(x), y(y) {}
};

void BfsFill(int x,int y,char c)
{
    Point s(x, y);
    queue<Point>q;
    q.push(s);
    while (!q.empty())
    {
        Point cur = q.front();
        q.pop();
        int tx = cur.x;
        int ty = cur.y;
        map[tx][ty] = c;
        for (int i = 0; i <= 3; i++)
        {
            //下一个点
            int nx = tx + offx[i];
            int ny = ty + offy[i];
            //到达边界
            if (nx < 0 || nx >= m || ny <= 0 || ny >= n) continue;

            //撞到了线或者已经是该字符了
            if (map[nx][ny] == c ||
                map[nx][ny] == '-' ||
                map[nx][ny] == '|' ||
                map[nx][ny] == '+') continue;

            q.push(Point(nx, ny));
        }
    }
}

void DfsFill(int x, int y, char c)
{
    //撞了边界
    if (x < 0 || x >= m || y < 0 || y >= n) return;

    //已经是此字符
    if (map[x][y] == c) return;

    if (map[x][y] != '-' && map[x][y] != '|' && map[x][y] != '+')
    {
        map[x][y] = c;
        for (int i = 0; i <= 3; i++)
        {
            DfsFill(x + offx[i], y + offy[i], c);
        }
    }
}


int main()
{
    ios::sync_with_stdio(false);
    
    cin >> m >> n >> op;//实际上map[m][i]和map[i][n]是边界,这里没有图

    for(int i=0;i<n;i++)
        for (int j = 0; j < m; j++)
        {
            map[j][i] = '.';
        }

    int opnum, x1, y1, x2, y2;
    char tc;
    for (int i = 0; i < op; i++)
    {
        cin >> opnum;
        if (opnum == 0)
        {
            cin >> x1 >> y1 >> x2 >> y2;
            DrawLine(x1, y1, x2, y2);
        }
        else if (opnum == 1)
        {
            cin >> x1 >> y1 >> tc;
            //BfsFill(x1, y1, tc);
            DfsFill(x1, y1, tc);
        }
    }

	//上下颠倒过来输出,因为题目中说了左下角为(0,0)
	//而个人理解里的数组是左上角为(0,0)
	//不同的人对数组的理解可能不一样
    for (int i = n - 1; i >= 0; i--)
    {
        for (int j = 0; j < m; j++)
        {
            cout << map[j][i];
        }

        cout << endl;
    }

    return 0;
}


发布了21 篇原创文章 · 获赞 3 · 访问量 410

猜你喜欢

转载自blog.csdn.net/qq_44506233/article/details/104986579