zoukankan      html  css  js  c++  java
  • SCAU 8634 字符菱形

    8634 字符菱形

    时间限制:500MS  内存限制:1000K 提交次数:0 通过次数:0

    题型: 编程题   语言: 无限制

    Description

    zayhero 在印度比赛时的纪念品是一幅精致的竹叶画。他在看其他选手的竹叶画时发现其中一幅是以字符
    菱形为基础画出来的。下图就是半径为1---5 时的字符菱形。

    那幅画的构图,就是将很多个半径为10 的字符菱形不断延伸画成。由于这种图案包含了太多字符,所以
    zayhero 觉得很混乱,为了理清思路,他需要知道画面上的字符分别有多少个。但由于画面太大了,所以
    他每次只能看到画面的一部分,假设这个部分是一个矩形,请计算该矩形内部某种字符的个数。
    在下面的图中,黄色部分的左上角为(13, 12),右下角为(53, 25),这个区域内没有字符a,但有12 个字
    符e,49 个字符i,58 个字符j。

    Input

    第一行,一个整数T (T <= 500),为测试数据组数。
    之后2T 行,每2 行表示一组测试数据。每组数据
    第一行,一个字符ch,表示需要计算个数的字符种类(a <= ch <= j)。
    第二行,四个整数X1,Y1,X2,Y2,(1<=X1 <= X2<=50000,1<=Y1 <= Y2<=50000),表示询问
    的矩阵的范围,其中(X1,Y1)为矩形左上角,(X2,Y2)为右下角。
    请注意,在本问题中,原点在左上角,而非一般的左下角。

    Output

    每组数据输出一行,输出需要计算的字符个数,具体格式见sample。

    Sample Input

    8
    j
    1 1 19 19
    a
    1 1 1 1
    a
    13 12 53 25
    e
    13 12 53 25
    i
    13 12 53 25
    j
    13 12 53 25
    f
    13 23 33 333
    g
    2 2 100 100
    

    Sample Output

    Case 1: 36
    Case 2: 0
    Case 3: 0
    Case 4: 12
    Case 5: 49
    Case 6: 58
    Case 7: 397
    Case 8: 630
    

    Hint

    
    

    Source

    Zayhero

    Provider

    admin

     

    #include<stdio.h>
    #include<string.h>
    int main()
    {
        int alpha[22][22], word[10];
        int x1, y1, x2, y2, k1, k2, i, j, t, T, cnt, x, y, m, n, max, nflag, mflag, n1;
        char temp, ch;
        
        // 构造字符菱形 
        memset(alpha, 1, sizeof(alpha));
        memset(word, 0, sizeof(word));
        for(i=1; i<20; ++i)
        {
            k1 = i>10? i%10 : 10 - i;  
            for(j=k1+1; j<=19-k1; ++j)
            {
                k2 = j>10? j-19 : 1-j;
                t = i>10?  k2+i-10 : k2+10-i;
                alpha[i][j] = t;
                word['j'+t-97]++; 
            }
        }
        // 构造完成
        
        scanf("%d", &T);
        t = T; 
        while(T--)
        {
            getchar();
            scanf("%c", &ch);
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            if(x1 > x2) 
            {x1 ^= x2; x2 ^= x1; x1 ^= x2;}
            if(y1 > y2)
            {y1 ^= y2; y2 ^= y1; y1 ^= y2;}
            cnt = nflag = mflag = 0;
            k2 = 0;
            if((n = (y2-y1+1)/19) > 0)  nflag = 1;
            if((m = (x2-x1+1)/19) > 0)  mflag = 1;
            if(mflag && nflag) 
            {
                cnt = n*m*word[ch-97];
                n = (y2-y1+1)%19, m = (x2-x1+1)%19;
                
                
                k2 = 0;
                for(i=y2-n+1; i<=y2; ++i)
                for(j=1; j<20; ++j)
                if((k1 = alpha[i%19? i%19 : 19][j]) <= 0 && ch == 'j'+ k1) k2++;
                  n1 = (x2-x1+1)/19;
                  cnt = cnt + n1*k2;
                
                
            /*    for(i=y2-n+1; i<=y2; ++i)
                for(j=x1; j<=x2; ++j)   //这里要超时 
                {
                    x = i%19? i%19 : 19;
                    y = j%19? j%19 : 19;
                    if((k1 = alpha[x][y]) <= 0 && ch == 'j'+ k1) ++cnt;
                }
            */    
                
                k2 = 0;
                for(i=1; i<20; ++i)
                for(j=x2-m+1; j<=x2; ++j)
                if((k1 = alpha[i][j%19? j%19 : 19]) <= 0 && ch == 'j'+ k1) k2++;
                n1 = (y2-y1+1)/19;
                cnt = cnt + n1*k2;
            
            /*    
                for(j=x2-m+1; j<=x2; ++j)
                for(i=y1; i<=y2; ++i)  //这里要超时 
                {
                    x = i%19? i%19 : 19;
                    y = j%19? j%19 : 19;
                    if((k1 = alpha[x][y]) <= 0 && ch == 'j'+ k1) ++cnt;
                }
                */
            
                for(i=y2-n+1; i<=y2; ++i)
                for(j=x2-m+1; j<=x2; ++j)
                {
                    x = i%19? i%19 : 19;
                    y = j%19? j%19 : 19;
                    if((k1 = alpha[x][y]) <= 0 && ch == 'j'+ k1) ++cnt;
                }
            }
            
            else if(!mflag && !nflag)
            {
                for(i=y1; i<=y2; ++i)
                for(j=x1; j<=x2; ++j)
                {
                    x = i%19? i%19 : 19;
                    y = j%19? j%19 : 19;
                    if((k1 = alpha[x][y]) <= 0 && ch == 'j'+ k1) ++cnt;
                }
            }
            else 
            {
                if(nflag)
                {
                    k2 = 0;
                    for(i=1; i<20; ++i)
                    for(j=x1; j<=x2; ++j)
                    if((k1 = alpha[i][j%19? j%19 : 19]) <= 0 && ch == 'j'+ k1) k2++;
                    n1 = (y2-y1+1)/19;
                    cnt = cnt + n1*k2;
                    
                    n = (y2-y1+1)%19;
                    for(i=y2-n+1; i<=y2; ++i)
                    for(j=x1; j<=x2; ++j)
                    if((k1 = alpha[i%19? i%19 : 19][j%19? j%19 : 19]) <= 0 && ch == 'j'+ k1) cnt++;
                    
                }
                
                if(mflag)
                {
                    k2 = 0;
                    for(i=y1; i<=y2; ++i)
                    for(j=1; j<20; ++j)
                    if((k1 = alpha[i%19? i%19 : 19][j]) <= 0 && ch == 'j'+ k1) k2++;
                    n1 = (x2-x1+1)/19;
                    cnt = cnt + n1*k2;
                    
                    m = (x2-x1+1)%19;
                    for(i=y1; i<=y2; ++i)
                    for(j=x2-m+1; j<=x2; ++j)
                    if((k1 = alpha[i%19? i%19 : 19][j%19? j%19 : 19]) <= 0 && ch == 'j'+ k1) cnt++;
                }
            }
            
            printf("Case %d: %d\n", t-T, cnt);
        } 
        
    
        return 0;
    } 


    解题报告:

    之前有编写菱形的经验,原本以为只是找输出如图菱形的规律需要消耗大部分的时间,刚输出完整的菱形时松了一口气,觉得接下来就容易处理多了

    根据题目意思,输入坐标,然后充分利用求模遍历就行了,检验没错后提交,超时?? 下来输入测试数据1 1 50000 50000 老半天才出来,看了一下这时判断字符的次数达到50000*50000,后来率先就改了菱形的构造函数,处理掉了一些不必要的判断和循环,(必须小心翼翼的,错了一个你不知道影响有多大!……)我想主要不是在这里啊,问题是遍历这里啊,后来想到干脆将一个菱形中所有出现的字符(毕竟只有a~j)个数都存储起来words,为了是看后面整个坐标划成的区域(矩形S)中有几个如此的菱形n, 然后先确定整的总数cnt = n*words; 而接下来的就处理剩余的部分:

                                      图1                                                                     图2

    蓝色的部分为n = 2 此时剩余蓝色线条圈住的空白,而我再次超时的做法是:

    分别直接处理红色和黄色的部分,最后减去重叠部分(浅绿),此时输入1 1 50000 50000 并没有等很久才出现结果,但提交还是WA,下来分析原因还是发现不够简,尽管处理了整块的部分,但(y2-y1)和 (x2-x1)还可以很大的,最大可以达到2*50000*18, 此时应该再处理。
     

                 图3                          图4 

                           图5

    情况一:(连接图1图2得到的图3)

    先计算黑色的圈子里有几个所需要的字符,这时用不到word统计出来的数据,需在构造菱形时的数组里存储相应的字符,从而可以拿到现在来统计,然后计算有多少个这样的块m,比如所说这里在右边的竖直方向上有2块(下面的红色那块不算,因为大家的长和宽都不相同,尽管这里看上去相同,但实质上是由(x2-x1)%19 和 (y2-y1)%19 决定的)。

    在水平方向上也这样处理,这时会剩下浅绿色的那块未计算,这块的长和宽分别是(x2-x1)%19 和 (y2-y1)%19 (那条是长那条是宽由自己决定)计算此块内所需统计的字符后加到总数中。

    情况二:(图4)

    (y2-y1) 异或 (x2-x1)超出了19,假设(x2-x1)>19这时跟处理上面的黑色那块一样,先计有在n=(x2-x1)/19, 然后得到(x2-x1)%19 和 (y2-y1) 围成的矩形中有多少个所需统计的字符,再与n相乘,而剩下的跟处理上图的浅绿色方块一样。

    情况三:(图5)

    这种情况最简单,直接计算围城的矩形里有多少需要统计的字符,但还是要对坐标求模计算。

    个人情况:

    花的事件可谓是不少啊,最后处理超时时,思维混乱了一个晚上,从下午7点到晚上1点多,好像时间都花在上面了,#¥&#@&&…… 但还比不上早上上课时用笔画图分情况思考,

    而回来写代码的时候,在很多的复制过程中还是将 i 用成了j, 比如说: k1 = alpha[ij%19? j%19 : 19][j%19? j%19 : 19] 又不得不调试了一番……

    思维能力自己感觉比别人欠缺了不少啊,严谨和周密、细心永远不能少!!!!!!

  • 相关阅读:
    [LeetCode-JAVA] Count Complete Tree Nodes
    [LeetCode-JAVA] Shortest Palindrome
    [LeetCode-JAVA] Best Time to Buy and Sell Stock IV
    [LeetCode-JAVA] Word Ladder II
    [LeetCode-JAVA] Jump Game II
    Keil开发的ARM程序main函数之前的汇编分析
    STM32平台SD卡的FatFS文件系统开发
    STM32 Cortex-M3 NMI异常
    应对STM32 Cortex-M3 Hard Fault异常
    LwIP协议栈开发嵌入式网络的三种方法分析
  • 原文地址:https://www.cnblogs.com/liaoguifa/p/2787485.html
Copyright © 2011-2022 走看看