• ZOJ 简单题集合(四)


    (1)ZOJ 1016. Parencodings

    题意:把一个括号表达式 S,从 P 编码转换为 W 编码。

    P 编码:P = P1,P2, ... , Pn; 其中 Pi  是 S 的第 i 个右括号前面的左括号个数。

    W 编码:W = W1, W2, ... , Wn; 对于 S 中的某一个右括号 a,Wi 是从与 a 匹配的左括号开始数起,数到 a 为止的右括号个数。

    例如:S (((()()())))
    P-编码: 4 5 6 6 6 6;
    W-编码: 1 1 1 4 5 6;

    分析:编码的元素个数就是右括号个数,也就是字符串S的一半长度。根据 P 编码建立起 S 字符串,然后根据 W 编码的定义进行转换。这里转换成 W 编码时,虽然是线性扫描,但是存在重复扫描的现象,但并没有利用已经扫描过的信息。潜意识里感觉有可能有优化的余地。不过这个题目规模很小,所以意义不大。

    zoj_1016
    #include <stdio.h>
    #include <string.h>
    
    char str[256];
    
    /* 根据 P 编码建立括号表达式 */
    void init_from_p(int* p, int length)
    {
        int i, j;
        int index = 0;
        int left_count = 0;
    
        for(i = 0; i < length; i++)
        {
            for(j = 0; j < (p[i] - left_count); j++)
            {
                str[index] = '(';
                ++index;
            }
            left_count = p[i];
            str[index] = ')';
            ++index;
        }
        str[index] = '\0';
    }
    
    /* 根据建立的括号表达式转换到 W 编码 */
    void convert_to_w(int* w)
    {
        int index = 0, depth = 0;
        int right_count = 0;
        char *p = str, *p2;
        while(*p)
        {
            if(*p == ')')
            {
                right_count = 1;
                depth = 1;
                p2 = p - 1;
                while(depth > 0)
                {
                    if(*p2 == ')')
                    {
                        right_count++;
                        depth++;
                    }
                    else if(*p2 == '(')
                        depth--;
                    --p2;
                }
                w[index] = right_count;
                ++index;
            }
            ++p;
        }
    }
    
    int main(int argc, char* argv[])
    {
        int t, n, i, j;
        int p[24], w[24];
    
        scanf("%ld", &t);
        for(i = 0; i < t; i++)
        {
            scanf("%ld", &n);
            for(j = 0; j < n; j++)
                scanf("%ld", p + j);
    
            memset(str, 0, sizeof(str));
            init_from_p(p, n);
            convert_to_w(w);
    
            for(j = 0; j < (n - 1); j++)
                printf("%ld ", w[j]);
    
            printf("%ld\n", w[j]);
        }
        return 0;
    }

    (2)ZOJ 1434. Frogger's For Dinner

    题意:一个比较有趣的模拟题目。一只青蛙要横穿过马路,马路中间有双向的 8 车道,上面分布着汽车,用 10 X 10 的网格表示。青蛙可以从选择任何一列向下穿越(之后青蛙只能位于这一列),汽车是“折回式”循环行驶的,即每一行(车道)上的汽车的速度相同(以免发生车祸)。青蛙前进的规则是,青蛙先前进一行,然后所有汽车沿着自己的方向前进 N 格,如果青蛙撞到汽车(重叠),或者汽车走过的轨迹覆盖到了青蛙的位置,则青蛙被杀死。题目要求的本质是判断青蛙是否能够成功穿过马路。

    分析:如果有汽车的速度是 9,显然该汽车一次移动轨迹可以完整覆盖所有列,则青蛙必然无法穿过。如果一行上摆满 10 辆汽车,显然青蛙也无法穿过。这可以使我们提前确定答案。注意,事后发现下面的代码中直接对 map 做了实时改动,但是也 AC 了,深层原因我没有去想。实际上每尝试一列,都应该使用 map 的全新副本进行模拟,map 本身不要进行任何变动。 

    zoj_1434
    #include <stdio.h>
    #include <string.h>
    
    char map[10][10];
    
    /* run one row down. return 1 if the frog is alive */
    /* row, col: the position of the frog */
    int run(int frogRow, int frogCol)
    {
        char tmpRow[12];
        int row, col;
        int x2;
        int bAliving = 1;
        for(col = 0; col < 10; col++)
        {
            if(map[frogRow + 1][col] != 0)
            {
                if(frogRow + 1 <= 4)
                    x2 = col - map[frogRow + 1][col];
                else
                    x2 = col + map[frogRow + 1][col];
                
                /* the frog is killed ? */
                if(x2 < 0)
                {
                    if(frogCol <= col || frogCol >= (x2 + 10))
                        return 0;
                }
                else if(x2 > 9)
                {
                    if(frogCol >= col || frogCol <= (x2 - 10))
                        return 0;
                }
                else
                {
                    if((frogCol - col) * (frogCol - x2) <= 0)
                        return 0;
                }
            }
        }
    
        /* make the vehicles run */
        for(row = 1; row <= 8; row++)
        {
            memset(tmpRow, 0, sizeof(tmpRow));
            for(col = 0; col < 10; col++)
            {
                if(map[row][col] != 0)
                {
                    if(row <= 4)
                        x2 = col - map[row][col];
                    else
                        x2 = col + map[row][col];
                    
                    if(x2 < 0) x2 += 10;
                    else if(x2 > 9) x2 -= 10;
    
                    tmpRow[x2] = map[row][col];
                }    
            }
            memcpy(map[row], tmpRow, 10);
        }
        return 1;
    }
    
    int can_across()
    {
        int frogRow, frogCol;
        for(frogCol = 0; frogCol < 10; frogCol++)
        {
            frogRow = 0;
            while(1)
            {
                if(run(frogRow, frogCol))
                    frogRow++;
                else
                    break;
    
                if(frogRow == 9)
                    return 1;
            }
        }
        return 0;
    }
    
    int main(int argc, char* argv[])
    {
        char line[48];
        int i, j, car_count;
        int bCanAcross;
        while(gets(line) != NULL) /* START */
        {
            bCanAcross = 1; /* resume the frog can across.*/
            memset(map, 0, sizeof(map));
            for(i = 1; i <= 8; i++)
            {
                gets(line);
                car_count = 0;
                for(j = 0; j < 10; j++)
                {
                    map[i][j] = line[j * 2] - '0';
                    if(map[i][j] == 9)
                        bCanAcross = 0; /* the car's speed is too fast! */
                    if(map[i][j] != 0)
                        car_count++;
                }
                if(car_count == 10) /* there are too many cars */
                    bCanAcross = 0;
            }
            gets(line); /* END */
    
            if(bCanAcross)
                bCanAcross = can_across(); /* test which col can across */
    
            if(bCanAcross) printf("LEFTOVER POSSUM\n");
            else printf("FROGGER\n");
        }
        return 0;
    }

    (3)ZOJ 1707. Automatic Editing

    题意:给出一个字符串,和 n 条查找替换规则。依次应用这些规则,然后输出处理后的结果。注意,1)每次都从头开始搜索要替换的字符串;2)一旦使用完了某条规则(即要查找的单词不再出现),之后就不能再次使用这条规则。3)大小写重要。

    zoj_1707
    #include <stdio.h>
    #include <string.h>
    
    char find[10][96];
    char replace[10][96];
    
    void edit(int n, char* text, char* result)
    {
        int i, len;
        char tmp[256];
        char* p = NULL;
        strcpy(tmp, text);
        for(i = 0; i < n; i++)
        {
            len = strlen(find[i]);
            while((p = strstr(tmp, find[i])) != NULL)
            {
                *p = 0;
                sprintf(result, "%s%s%s", tmp, replace[i], p + len);
                strcpy(tmp, result);
            }
        }
    }
    
    int main(int argc, char* argv[])
    {
        char line[256], result[256];
        int n, i;
        while(1)
        {
            scanf("%ld", &n);
            if(n == 0) break;
            getchar(); /* discard the newline char */
            for(i = 0; i < n; i++)
            {
                gets(find[i]);
                gets(replace[i]);
            }
            gets(line);
            edit(n, line, result);
            printf("%s\n", result);
        }
    
        return 0;
    }

    (4)ZOJ 1879. Jolly Jumpers

    题意:一个由 n 个整数组成的数列,如果相邻元素的差值的绝对值恰好为 1 到 n-1,则该数列被称称为 jolly jumper。

    例如:[ 1 4 2 3 ] 是一个 jolly jumper,因为其相邻元素的差值的绝对值分别是 3,2,1。只包含一个元素的数列也定义为 jolly jumper。判断一个给定的数列是否是 jolly jumper。(n < 3000 )

    zoj_1879
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    
    char flags[3000];
    
    int main(int argc, char* argv[])
    {
        int n, i, lastNum, curNum, tmp;
        int bFindResult, bIsJolly;
        while(scanf("%ld", &n) != EOF)
        {
            memset(flags, 0, sizeof(flags));
    
            bFindResult = 0;
            bIsJolly = 1;
    
            scanf("%ld", &lastNum);
            for(i = 1; i < n; i++)
            {
                scanf("%ld", &curNum);
    
                if(bIsJolly)
                {
                    tmp = (int)fabs(curNum - lastNum);
                    lastNum = curNum;
    
                    if(tmp == 0 || tmp > n-1 || flags[tmp])
                        bIsJolly = 0;
                    else
                        flags[tmp] = 1;
                }
            }
    
            if(bIsJolly) printf("Jolly\n");
            else printf("Not jolly\n");
        }
        return 0;
    }

    (5)ZOJ 1889. Ones (本文重点)

    题意:给出一个不能被 2 和 5 整除的整数 n (0 <= n <= 10000),它的某个倍数用 10 进制表示全部是 1 组成。问符合这个条件的倍数数字由多少个 1 组成。

    例如:n = 7 时, 7 * 15873 = 111111;包含 6 个 1,因此结果为 6。

    分析:可以很明显的看到,该体产生的数字已经远超过整型类型表达的范围。因此不能试图用整型去寻找该倍数。根据题目,我们只需要确定存在这样一个数字,由 m 个 1 组成,它能被 n 整除。因此只需要试验 m 的值,从 1 开始逐渐增加,直到找到第一个可以被 n 整除的数字为止。我们只需要考虑该数字除以 n 的余数即可(即 mod n)。假设 m 时余数为 remain,容易得出 m = m + 1 时,余数为 (remain * 10 + 1) mod n; 

    zoj_1889
    #include <stdio.h>
    int main(int argc, char* argv[])
    {
        int n, result, remain;
        while(scanf("%ld", &n) != EOF)
        {
            remain = 1 - 1 / n * n;
            result = 1;
            while(remain != 0)
            {
                result++;
                remain = remain * 10 + 1;
                remain = remain - remain / n * n;
            }
            printf("%ld\n", result);
        }
        return 0;
    }


    (6)ZOJ 2423. Fractal

    题意:要求打印出一个分形图。分形图用X字符表示,定义如下表。要求绘制出度数为 n (n <= 7) 的分形图。

    degree box fractal
    1 X
    2

    X  X

      X

    X  X

    用 B(n-1) 表示 n-1 度  

    B(n-1)            B(n-1)

              B(n-1)

    B(n-1)            B(n-1)

    注意:任何一行结尾不可以有多余的空格,否则将会导致“Presentation Error”。

    分析:采用根据其递归定义,用递归函数初始化出一个模板,然后滤除每一行结尾的空格后输出即可。代码中使用了 5 个对 B(n-1)的调用,这里实际上 5 个子矩阵的内容是完全一样的,因此只需要调用一次左上角的 B(n-1),然后把它拷贝到其他四个位置即可,这样可以大大减少递归调用次数,提高代码效率。此题目度数很小,因此可以不做出优化。

    zoj_2423
    #include <stdio.h>
    #include <string.h>
    
    char map[732][732];
    
    void fractal(int n, int row, int col, int length)
    {
        if(n == 1)
        {
            map[row][col] = 'X';
            return;
        }
        else
        {
            int k = length / 3;
            fractal(n-1, row, col, k);
            fractal(n-1, row, col + k * 2, k);
            fractal(n-1, row + k, col + k, k);
            fractal(n-1, row + k * 2, col, k);
            fractal(n-1, row + k * 2, col + k * 2, k);
        }
    }
    
    void trim(int length)
    {
        int row, col;
        for(row = 0; row < length; ++row)
        {
            for(col = length; col >= 0; --col)
                if(map[row][col] == 'X') break;
    
            map[row][col + 1] = '\0';
        }
    }
    
    void print_map(int length)
    {
        int row;
        for(row = 0; row < length; ++row)
            printf("%s\n", map[row]);
        printf("-\n");
    }
    
    int main(int argc, char* argv[])
    {
        int length[] = { 0, 1, 3, 9, 27, 81, 243, 729 };
        int n;
        while(scanf("%ld", &n) != EOF)
        {
            if(n < 0) break;
            memset(map, ' ', sizeof(map));
            fractal(n, 0, 0, length[n]);
            trim(length[n]);
            print_map(length[n]);
        }
        return 0;
    }

    (7)ZOJ 2886. Look and Say

    题意:字符串处理题目。一个字符串 122344111 可以被描述为“1个1,2个2,1个3,2个4,3个1”。因此,其后继是“1122132431”。类似的,1111111111 后继是 101。通常一个字符串的前继不是唯一的,例如 112213243 个 1 组成的数字,后继也是 1122132431。给出一个字符串,输出它的后继。

    zoj_2886
    #include <stdio.h>
    void look_say(char *text)
    {
        char *p = text;
        int count = 0;
        while(*p)
        {
            count = 1;
            while(p[1] == p[0])
            {
                ++count;
                ++p;
            }
            printf("%ld%c", count, *p);
            ++p;
        }
    }
    
    int main(int argc, char* argv[])
    {
        char line[1024];
        int n, i;
        scanf("%ld\n", &n);
        for(i = 0; i < n; i++)
        {
            gets(line);
            look_say(line);
            printf("\n");
        }
        return 0;
    }


    (8)ZOJ 3488. Conic Section

    题意:给出方程 ax2+bxy+cy2+dx+ey+f=0 的系数,判断该曲线是圆,椭圆,双曲线还是抛物线。

    分析:此题比较坑爹,反复提交失败后,我忍不住搜索了这个题目。原来方程的系数应该定义为浮点数,而不是整数!了解此题后,则此题毫无难度,尽管给了一个比较有趣的平面截双圆锥的图,但纯属科普作用。

    zoj_3488
    #define EQUAL(a, b) (fabs((a)-(b)) < 0.0000001)
    
    #include <stdio.h>
    #include <math.h>
    
    int main(int argc, char* argv[])
    {
        int T, i;
        double a, b, c, d, e, f;
        scanf("%ld", &T);
        for(i = 0; i < T; i++)
        {
            scanf("%lf %lf %lf %lf %lf %lf", 
                &a, &b, &c, &d, &e, &f);
    
            if(EQUAL(a*c, 0))
                printf("parabola\n");
            else if(a*c > 0)
            {
                if(EQUAL(a, c))
                    printf("circle\n");
                else
                    printf("ellipse\n");
            }        
            else if(a*c < 0)
                printf("hyperbola\n");
        }
        return 0;
    }
  • 相关阅读:
    我的NopCommerce之旅(8): 路由分析
    我的NopCommerce之旅(7): 依赖注入(IOC/DI)
    我的NopCommerce之旅(6): 应用启动
    我的NopCommerce之旅(5): 缓存
    我的NopCommerce之旅(4): 定时任务之邮件
    我的NopCommerce之旅(3): 系统代码结构分析
    我的NopCommerce之旅(2): 系统环境及技术分析
    我的NopCommerce之旅(1): 系统综述
    关于CSS中部分浏览器兼容性问题的解决
    每天一个Js小demo之移动端全景图场景实现-全景装修图。主要知识点:css3,旋转角度检测
  • 原文地址:https://www.cnblogs.com/hoodlum1980/p/2580255.html
Copyright © 2020-2023  润新知