CSP真题_2015_3 画图(BFS在csp考题中的应用场景)

本文通过一道CSP真题,探讨如何使用BFS算法在ASCII画布上进行画线和填充操作。题目要求用水平线段(-)、竖直线段(|)和交点(+)构建图形,并支持填充指定字符。解决方案涉及BFS的基本应用和边界条件判断,适合初学者了解BFS在图形绘制问题中的应用。
摘要由CSDN通过智能技术生成

总述

题目概述

BFS是算法中比较简单和初级的算法,但由于其在解决图论及一些多维空间问题上的易实现性,在很多程序设计题目中频繁出现。在解决问题时,如果设计出了一个BFS或其同类的DFS算法,只要证明这个算法在时空复杂度上都满足条件,就可以果断实现。如果发现部分数据无法满足,且当前没有其他好的思路,也可以将其作为一种得部分分数的方式在CSP中使用。

原题描述

问题描述
用 ASCII 字符来画图是一件有趣的事情,并形成了一门被称为 ASCII Art 的艺术。
本题要求编程实现一个用 ASCII 字符来画图的程序,支持以下两种操作:
1、画线:给出两个端点的坐标,画一条连接这两个端点的线段。简便起见题目保证要画的每条线段都是水平或者竖直的。水平线段用字符 - 来画,竖直线段用字符 | 来画。如果一条水平线段和一条竖直线段在某个位置相交,则相交位置用字符 + 代替。
2、填充:给出填充的起始位置坐标和需要填充的字符,从起始位置开始,用该字符填充相邻位置,直到遇到画布边缘或已经画好的线段。注意这里的相邻位置只需要考虑上下左右 4 个方向。

INPUT

第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个操作按照数据给出的顺序依次执行。画布最初时所有位置都是字符 .(小数点)。

OUTPUT

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

输入输出案例

样例一
输入:

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

输出:

AAAA
A----A

样例二
输入:

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

输出:
在这里插入图片描述

题目重述

给定一个要输出的画布大小(长m×宽n)和要进行的操作个数q个。且该画布的所有点被初始化为’’.’’,初始状态没有画线。
操作一共有两种:
操作提示符为0则是画线操作,从输入的(x1,y1)到(x2,y2)画线,且注意题目的输入数据保证完成一次画线所画出的一定是一条直线,也就是一定有x1==x2或者y1==y2。
操作提示符为1,则是填充操作,从给定的出发点(x,y)开始填充输入的字符,到达画布的边界或者画出的线填充停止。(明显是迷宫问题的改版)
输出时,输出每个位置的字符,有如下几种情况:
1、有横线有竖线,输出“+”
2、有横线无竖线,输出“-”
3、无横线有竖线,输出“|”
4、无横线无竖线,有填充,输出填充字符
5、无横线无竖线,无填充,输出“.”
且要注意的是输出画布是从画布的最上方开始输出,要注意输出时的遍历参数。
题目的背景与字符串有关,看似是一道字符串题目,但只要大致理解题意我们就会发现这是一道典型的BFS题目。主要考察的就是对于数据存储的功力,而BFS部分则可以经过转换,变成和迷宫问题一样情景的板子题,在算法设计上没有太大难度。

解题思路

思路概述

关于输入输出部分只是一些特判,在此处就不加说明了。
关于画线操作,由于规定一定画直线,只需要分情况讨论直线的走向和存储,在算法设计上没有难度。画线操作的函数如下:

void make_line(int x_1,int y_1,int x_2,int y_2)
{
   
    if(x_1==x_2)//纵向划线
    {
   
        if(y_1==y_2)//不划线
        return;
        else if(y_1>y_2)//向下划线
        {
   
            for(int i=y_2;i<=y_1;i++)
            {
   
                a[x_1][i].long_direct=1;
            }
        }
        else
        {
   
            for(int i=y_1;i<=y_2;i++)//向上划线
            {
   
                a[x_1][i].long_direct=1;
            }
        }
    }
    else if(y_1==y_2)//横向划线
    {
   
        if(x_1>x_2)//向左划线
        {
   
            for(int i=x_2;i<=x_1;i++)
            {
   
                a[i][y_1].wide_direct=1;
            }
        }
        else
        {
   
            for(int i=x_1;i<=x_2;i++)
            {
   
                a[i][y_1].wide_direct=1;
            }
        }   
    }
}

在填充部分,核心算法便是迷宫问题的板子。要注意的是,边界条件较多有下列几个:
1、BFS只在xy的正半轴进行,也就是要满足BFS到的点满足横纵坐标>=0
2、BFS到的点不能超过画布的范围,横纵坐标满足<width,length
3、BFS过程中只有遇到横划线和纵划线都满足flag==0,才将该点push进队列中,且要注意后面的填充要覆盖前面的填充。
填充部分代码如下࿱

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值