2022-1-19 每日一题 HDU 2074 叠筐

题目描述:

叠筐
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 23830 Accepted Submission(s): 6282

Problem Description
需要的时候,就把一个个大小差一圈的筐叠上去,使得从上往下看时,边筐花色交错。这个工作现在要让计算机来完成,得看你的了。

Input
输入是一个个的三元组,分别是,外筐尺寸n(n为满足0< n <80的奇整数),中心花色字符,外筐花色字符,后二者都为ASCII可见字符;

Output
输出叠在一起的筐图案,中心花色与外筐花色字符从内层起交错相叠,多筐相叠时,最外筐的角总是被打磨掉。叠筐与叠筐之间应有一行间隔。

链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2074https://www.nowcoder.com/practice/2d6505bf0d38479c9bff66e10fe39a5c

解题思路:

模拟类图形排版题

解法1:更优解法(模板)

利用缓存数组保存输出字符矩阵,再在数组上进行排版

解题分析:

  • 先不管4个角,补上成为一个正方形,最后剔除即可
  • 从外向内构造
  • 利用坐标 左上角(i, i) 右下角(j, j) 确定一圈
  • 利用奇偶性决定每圈填充字符c
  • 确定每圈边长length

注意点!!!:

  1. 输出格式——每组输出之间有一个空行
  2. 边界处理——除去n=1的情况,其余都需剔除4个角

代码如下:

#include <iostream>
#include <cstdio>

using namespace std;

char matrix[80][80];//矩阵模拟图形

int main() {
    int n;                                        //叠筐大小n
    char a,b;                                     //输入两个字符
    bool firstCase = true;                        //第一组数据
    while(scanf("%d %c %c", &n, &a, &b) != EOF) {
        if(firstCase == true){
            firstCase = false;
        } else {
            printf("\n");
        }
        for (int i = 0; i <= n/2; ++i) {          //(i,i)每圈 左上坐标
            int j = n - i - 1;                    //(j,j)每圈 右下坐标
            int length = n - 2 * i;               //每圈边长
            char c;
            if ((n / 2 -i) % 2 == 0) {            //求当前圈填充字符
                c = a;
            }else {
                c = b;
            }
            for (int k = 0; k < length; ++k) {    //当前圈赋值
                matrix[i][i + k] = c;             //上边
                matrix[i + k][i] = c;             //左边
                matrix[j][j - k] = c;             //下边
                matrix[j - k][j] = c;             //右边
            }
        }
        if (n != 1) {                             //去掉四个角
            matrix[0][0] = ' ';
            matrix[0][n-1] = ' ';
            matrix[n-1][0] = ' ';
            matrix[n-1][n-1] = ' ';
        }
        for (int i = 0; i < n; ++i) {             //打印
            for(int j = 0; j < n; ++j){
                printf("%c", matrix[i][j]);
            }
            printf("\n");                         //换行
        }
    }
    return 0;
}

解法2:

每行规律,按输出顺序,按行按列输出

解题分析:

初始代码:

逻辑直观,但是if-else嵌套过多

#include <stdio.h>
#include <stdlib.h>

void swap(char *a, char *b)
{
    char c = *a;
    *a = *b;
    *b = c;
}

int main()
{
    int n,i,j,r;//r即为row行号
    char a,b;//中心花色、外筐花色
    while(scanf("%d %c %c", &n, &a, &b) != EOF) {
        //特殊情况,n=1,即直接输出中心花色即可
        if(n == 1) {
            printf("%c\n\n",a);
            continue;
        }

        //根据中心字符是奇偶,给a,b赋值(默认中心:偶,外筐:奇)
        if((n / 2 + 1)%2 == 1) {
            swap(&a, &b);
        }
        //按行按列输出
        for(int i = 1; i <= n; ++i) { //行
            for(int j = 1; j <= n; ++j) { //列
                if(i > n / 2 + 1) {
                    r = n - i + 1;
                } else {
                    r = i;
                }
                if(r == 1) { //第一行和最后一行
                    if(j == 1 || j == n) {
                        printf(" ");
                    } else {
                        printf("%c",b);
                    }
                } else {
                    if(j < r || j > n-r+1) {
                        if(j % 2 == 1) {
                            printf("%c", b);//奇数为外筐花色
                        } else {
                            printf("%c", a);//偶数为中心花色
                        }
                    } else {
                        if(r % 2 == 1) {
                            printf("%c", b);//由行号决定中间连续的花色是哪个
                        } else {
                            printf("%c", a);
                        }
                    }
                }
            }
            printf("\n");
        }
        printf("\n");//每组输出间有一空行
    }
    return 0;
}

优化后代码:

减少if-else嵌套,更扁平化,但是代码可读性降低

#include <stdio.h>
#include <stdlib.h>

void swap(char *a, char *b)
{
    char c = *a;
    *a = *b;
    *b = c;
}

int main()
{
    int n,i,j,r;//r即为row行号
    char a,b;//中心花色、外筐花色
    while(scanf("%d %c %c", &n, &a, &b) != EOF) {
        //特殊情况,n=1,即直接输出中心花色即可
        if(n == 1) {
            printf("%c\n\n", a);
            continue;
        }
        //根据中心字符是奇偶,给a,b赋值(默认中心:偶,外筐:奇)
        if((n / 2 + 1)%2 == 1) {
            swap(&a, &b);
        }
        //按行按列输出
        for(int i = 1; i <= n; ++i) { //行
            for(int j = 1; j <= n; ++j) { //列
                r = (i > n / 2 + 1)? (n - i + 1) : i;//行号赋值
                if(r == 1 && (j == 1 || j == n)) { //第一行和最后一行头尾输出空格
                    printf(" ");
                    continue;
                }
                int p = (j < r || j > n - r + 1)? j : r;//确定花色 j决定从外到里的花色变换,r决定中间连续的花色
                if(p % 2 == 1) {
                    printf("%c", b);//j奇数为外筐花色
                } else {
                    printf("%c", a);//j偶数为中心花色
                }
            }
            printf("\n");
        }
        printf("\n");//每组输出间有一空行
    }
    return 0;
}
posted @ 2022-01-25 23:34  Jane8  阅读(33)  评论(0)    收藏  举报