【题目来源】
https://www.luogu.com.cn/problem/P1058
https://www.acwing.com/problem/content/description/438/
【题目描述】
小渊是个聪明的孩子,他经常会给周围的小朋友们讲些自己认为有趣的内容。最近,他准备给小朋友们讲解立体图,请你帮他画出立体图。
小渊有一块面积为 m×n 的矩形区域,上面有 m×n 个边长为 1 的格子,每个格子上堆了一些同样大小的积木(积木的长宽高都是 1),小渊想请你打印出这些格子的立体图。我们定义每个积木为如下格式,并且不会做任何翻转旋转,只会严格以这一种形式摆放:
+---+
/ /|
+---+ |高
| | +
| |/ 宽
+---+
长
每个顶点用 1 个加号 + 表示,长用 3 个 - 表示,宽用 1 个 /,高用两个 | 表示。字符 +,-,/,| 的 ASCII 码分别为 43,45,47,124。字符 .(ASCII 码 46)需要作为背景输出,即立体图里的空白部分需要用 . 来代替。立体图的画法如下面的规则:
若两块积木左右相邻,图示为:
..+---+---+
./ / /|
+---+---+ |
| | | +
| | |/.
+---+---+..
若两块积木上下相邻,图示为:
..+---+
./ /|
+---+ |
| | +
| |/|
+---+ |
| | +
| |/.
+---+..
若两块积木前后相邻,图示为:
....+---+
.../ /|
..+---+ |
./ /| +
+---+ |/.
| | +..
| |/...
+---+....
立体图中,定义位于第 (m,1) 的格子(即第 m 行第 1 列的格子)上面自底向上的第一块积木(即最下面的一块积木)的左下角顶点为整张图最左下角的点。
【输入格式】
输入文件第一行有用空格隔开的两个整数 m 和 n,表示有 m×n 个格子。
接下来的 m 行,是一个 m×n 的矩阵,每行有 n 个用空格隔开的整数,其中第 i 行第 j 列上的整数表示第 i 行第 j 列的格子上摞有多少个积木(1≤每个格子上的积木数≤100)。
【输出格式】
输出文件中包含题目要求的立体图,是一个 K 行 L 列的字符矩阵,其中 K 和 L 表示最少需要 K 行 L 列才能按规定输出立体图。
【数据范围】
1≤m,n≤50
【输入样例】
3 4
2 2 1 2
2 2 1 1
3 2 1 2
【输出样例】
......+---+---+...+---+
..+---+ / /|../ /|
./ /|-+---+ |.+---+ |
+---+ |/ /| +-| | +
| | +---+ |/+---+ |/|
| |/ /| +/ /|-+ |
+---+---+ |/+---+ |/| +
| | | +-| | + |/.
| | |/ | |/| +..
+---+---+---+---+ |/...
| | | | | +....
| | | | |/.....
+---+---+---+---+......
【算法分析】
● 依据题意,每个积木不会做任何翻转旋转,只会严格以给定的形式摆放。每个顶点用 1 个加号 + 表示,长用 3 个 - 表示,宽用 1 个 / 表示,高用 2 个 | 表示,空白部分需要用 . 来代替。此种给定的积木形式,以代码表示如下。
char box[6][8]={
"..+---+",
"./ /|",
"+---+ |",
"| | +",
"| |/.",
"+---+.."
};
● 解题思路:先把“积木形式”存在数组中,然后按照“从下往上,从后往前,从左往右”的顺序依次覆盖,之后输出即可。覆盖顺序来源于实际的模拟。
+---+ +---+ +---+
/ /| / /| / /|
+---+ | +---+ | +---+ |
+---+ | | + | | +---+ | | +---+
/ /| | |/| | |/ /| | |/ /|
+---+ | +---+ | +---+---+ | +---+---+ |
| | + | | + | | | + / /| | +
| |/ | |/ | | |/ +---+ | |/
+---+ +---+ +---+---+ | | +---+
| |/
+---+
【算法代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
char ch[maxn][maxn];
char box[6][8]= {
"..+---+",
"./ /|",
"+---+ |",
"| | +",
"| |/.",
"+---+.."
};
void draw(int x,int y) {
for(int i=0; i<6; i++)
for(int j=0; j<7; j++)
if(box[i][j]!='.')
ch[x+i][y+j]=box[i][j];
}
int main() {
memset(ch,'.',sizeof(ch));
int le=0;
int m,n;
cin>>m>>n;
int a[m][n];
int w=n*4+1+m*2;
for(int i=0; i<m; i++)
for(int j=0; j<n; j++) {
cin>>a[i][j];
le=max(le,a[i][j]*3+1+(m-i)*2);
}
for(int i=0; i<m; i++)
for(int j=0; j<n; j++)
for(int k=1; k<=a[i][j]; k++)
draw(le-(k*3)-2*(m-i),j*4+1+(m-i-1)*2);
for(int i=1; i<=le; i++) {
for(int j=1; j<=w; j++) cout<<ch[i][j];
cout<<endl;
}
return 0;
}
/*
in:
3 4
2 2 1 2
2 2 1 1
3 2 1 2
out:
......+---+---+...+---+
..+---+ / /|../ /|
./ /|-+---+ |.+---+ |
+---+ |/ /| +-| | +
| | +---+ |/+---+ |/|
| |/ /| +/ /|-+ |
+---+---+ |/+---+ |/| +
| | | +-| | + |/.
| | |/ | |/| +..
+---+---+---+---+ |/...
| | | | | +....
| | | | |/.....
+---+---+---+---+......
*/
【参考文献】
https://www.luogu.com.cn/problem/solution/P1058
https://www.acwing.com/solution/content/57301/
https://www.acwing.com/solution/content/4080/