CCF2015-12-3画图

Posted awangkuo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF2015-12-3画图相关的知识,希望对你有一定的参考价值。

第1行有三个整数mnqmn分别表示画布的宽度和高度,以字符为单位。q表示画图操作的个数。
  第2行至第q + 1行,每行是以下两种形式之一:
  ? 0 x1 y1 x2 y2:表示画线段的操作,(x1y1)和(x2y2)分别是线段的两端,满足要么x1 = x2 且y1 ≠ y2,要么 y1 = y2 且 x1 ≠ x2
  ? 1 x y c:表示填充操作,(xy)是起始位置,保证不会落在任何已有的线段上;c 为填充字符,是大小写字母。
  画布的左下角是坐标为 (0, 0) 的位置,向右为x坐标增大的方向,向上为y坐标增大的方向。这q个操作按照数据给出的顺序依次执行。画布最初时所有位置都是字符 .(小数点)。

本题自身的逻辑并不困难,在写出模拟改动之后,出了两个小问题,一次80,一次90,而且都不是第一时间找到问题所在,改动了很多次才通过,值得警醒。

第一个bug,答案错误,80分,那么是哪里错了呢,前面的样例基本正确且通过,至80分样例开始错误,一定是哪个特殊情况没有考虑到,这时候检查代码没有发现问题之后,最好重新读题,很可能是某句话理解有误。细读之后发现这句“如果一条水平线段和一条竖直线段在某个位置相交,则相交位置用字符 + 代替。”在我之前的理解之中,添加+号是在-添加时判断其上下有无|,有则+,无则-,|号同理。

这个理解是错的,题意是说如果在某位置相交,才会出现+号,那么如果|号刚好添加到了-号的上位,但并不相交,按我原来代码,是要出现+号的,自然大错特错。

第二个bug,时间超时,90分,说实话这个问题还是我第一次在ccf中遇到,ccf大多数时间都只有1s,拿出普通算法早已足够,在此问题出现之后,我多次改动,甚至修改了容器和字符串的初始化操作,可并未出现理想的有效结果,这使我意识到优化初始化并不能带来什么,那么,我的字母判断函数呢,我将自己定义的字母判断函数加了个引用,也无效,用系统自带的字母判断函数会不会效果好点?事实证明也是徒劳的。那么问题应该是出现在了算法的优化上。画线段本身逻辑简单,问题不在这里,在用队填充的过程中,我用了自己写的vector队,每次遍历都是j++,且满足条件后放到队尾,初看之下并无大碍,所以怎么也检查不出来,就试着去阅读满分的代码,看他们的逻辑结果,在这过程中福至心头,想到我的队列情况如果是第一行AA 第二行AB,从B开始填充,左上角的A竟然多次入队判断,非常浪费时间,指数级消耗无用判断,所以在这里也优化了一次,优先判断V【y】【x】是否为c,如果是,那么j++,直接continue,之前就访问过这里,进入下一次循环即可。如果不是,才有了将其改为c,并且进入队资格判断。至此,提交之后的代码是100分,不再超时。还有一个有意思的细节是,分别用了我的引用判断字母函数,和标准库里的字母函数,我自己的居然是900ms,标准库中984ms,那么,这多出来的84ms是哪里的问题呢?初步理解为isalpha(int c),用的是赋值,没用引用。也许是其设计之初针对一个字符的赋值即可并不需要引用?

转到其定义如下:

 template<typename _CharT>
    inline bool
    isalpha(_CharT __c, const locale& __loc)
    { return use_facet<ctype<_CharT> >(__loc).is(ctype_base::alpha, __c); }

恐怕我要到模板部分深入探索之后才能再下定论。

整体代码如下:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool isalp(char &c)
{
    if(c-a>=0 && c-a<26)
    return true;
    if(c-A>=0 && c-A<26)
    return true;
    return false;
}
int main()
{
//    第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个操作按照数据给出的顺序依次执行。画布最初时所有位置都是字符 .(小数点)。
    int m,n,q;
    cin>>m>>n>>q;
    string t(m,.);
    vector<string> v(n,t);
    for(int i=0;i<q;i++)
    {
        int mod;
        cin>>mod;
        if(mod==0)
        {

            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            if(y1==y2)
            {
            int y=y1;
            int minx=min(x1,x2);
            int maxx=max(x1,x2);
            for(int x=minx;x<=maxx;x++)
            {
                if(v[y][x]==|)
                v[y][x]=+;
                else if(v[y][x]!=+)
                v[y][x]=-;
            }
            }
            else if(x1==x2)
            {
                int x=x1;
                int miny=min(y1,y2);
                int maxy=max(y1,y2);
                for(int y=miny;y<=maxy;y++)
                {
                    if(v[y][x]==-)
                    v[y][x]=+;
                    else if(v[y][x]!=+)
                    v[y][x]=|;
                }
            }
        }
        else{
            //填充函数,是否用到队列
             int x3,y3;
             char c;
             cin>>x3>>y3;
             cin>>c;
             //创建一个队列,填充式补c
             vector<vector<int>> q;
             vector<int> temp;
             temp.push_back(x3);
             temp.push_back(y3);
             q.push_back(temp);
             temp.clear();
             int j=0;
             while(j!=q.size())
             {
                 int x=q[j][0];
                 int y=q[j][1];
                 if(v[y][x]!=c)
                 v[y][x]=c;
                 else{
                     j++;
                     continue;
                 }
                 if(y+1<n && v[y+1][x]!=c && (v[y+1][x]==. ||  isalpha(v[y+1][x])))
                 {
                     temp.push_back(x);
                     temp.push_back(y+1);
                     q.push_back(temp);
                     temp.clear();
                 }
                 if(y-1>=0 && v[y-1][x]!=c && (v[y-1][x]==. || isalpha(v[y-1][x])))
                 {
                     temp.push_back(x);
                     temp.push_back(y-1);
                     q.push_back(temp);
                     temp.clear();
                 }
                if(x-1>=0 && v[y][x-1]!=c && (v[y][x-1]==. || isalpha(v[y][x-1])))
                 {
                     temp.push_back(x-1);
                     temp.push_back(y);
                     q.push_back(temp);
                     temp.clear();
                 }
                 if(x+1<m && v[y][x+1]!=c && (v[y][x+1]==. || isalpha(v[y][x+1])))
                 {
                     temp.push_back(x+1);
                     temp.push_back(y);
                     q.push_back(temp);
                     temp.clear();
                 }
                 j++;
             }
            q.clear();
        }
    }
//    for(int i=0;i<n;i++)
//    {
//        v2.push_back(v[i]);
//    }
    for(int i=v.size()-1;i>=0;i--)
    {
        cout<<v[i]<<endl;
    }
    
    return 0;
}

 

  

以上是关于CCF2015-12-3画图的主要内容,如果未能解决你的问题,请参考以下文章

CCF CSP 201409-2 画图

CCF 201512-3画图 (DFS搜索+模拟)

CCF 201512-3 画图 100分

CCF 201512-3 画图 100分

CCF_ 201409-2_画图

CCF_ 201512-3_画图