首页 > 其他分享 >洛谷P1058 [NOIP2008 普及组] 立体图

洛谷P1058 [NOIP2008 普及组] 立体图

时间:2023-09-24 17:15:27浏览次数:47  
标签:maxy 积木 int +---+ 立体图 NOIP2008 verb P1058

写在前面

题解更新较少,请勿嗔怪。
本文粗鄙而简陋,要获得更好的阅读体验,请移步https://www.luogu.com.cn/problem/solution/P1058
NOIp普及组2008的第四题,题目网站https://www.luogu.com.cn/problem/P1058

关于题目

[NOIP2008 普及组] 立体图

题目描述

小渊是个聪明的孩子,他经常会给周围的小朋友们讲些自己认为有趣的内容。最近,他准备给小朋友们讲解立体图,请你帮他画出立体图。

小渊有一块面积为 \(m \times n\) 的矩形区域,上面有 \(m \times n\) 个边长为 \(1\) 的格子,每个格子上堆了一些同样大小的积木(积木的长宽高都是 \(1\)),小渊想请你打印出这些格子的立体图。我们定义每个积木为如下格式,并且不会做任何翻转旋转,只会严格以这一种形式摆放:

\[\def\arraystretch{1e-10} \begin{aligned} &\verb! +---+!\\ &\verb! / /|!\\ &\verb!+---+ |!\quad\textsf{高}\\ &\verb!| | +!\\ &\verb!| |/ !\quad\textsf{宽}\\ &\verb!+---+ !\\ & \quad\textsf{长} \end{aligned}\]

每个顶点用 \(1\) 个加号 + 表示,长用 \(3\) 个 - 表示,宽用 \(1\) 个 /,高用两个 | 表示。字符 +-/| 的 ASCII 码分别为 \(43\),\(45\),\(47\),\(124\)。字符 .(ASCII 码 \(46\))需要作为背景输出,即立体图里的空白部分需要用 . 来代替。立体图的画法如下面的规则:

若两块积木左右相邻,图示为:

\[\def\arraystretch{1e-10} \begin{aligned} \verb!..+---+---+!\\ \verb!./ / /|!\\ \verb!+---+---+ |!\\ \verb!| | | +!\\ \verb!| | |/.!\\ \verb!+---+---+..!\\ \end{aligned} \]

若两块积木上下相邻,图示为:

\[\def\arraystretch{1e-10} \begin{aligned} \verb!..+---+!\\ \verb!./ /|!\\ \verb!+---+ |!\\ \verb!| | +!\\ \verb!| |/|!\\ \verb!+---+ |!\\ \verb!| | +!\\ \verb!| |/.!\\ \verb!+---+..!\\ \end{aligned} \]

若两块积木前后相邻,图示为:

\[\def\arraystretch{1e-10} \begin{aligned} \verb!....+---+!\\ \verb!.../ /|!\\ \verb!..+---+ |!\\ \verb!./ /| +!\\ \verb!+---+ |/.!\\ \verb!| | +..!\\ \verb!| |/...!\\ \verb!+---+....!\\ \end{aligned} \]

立体图中,定义位于第 \((m,1)\) 的格子(即第 \(m\) 行第 \(1\) 列的格子)上面自底向上的第一块积木(即最下面的一块积木)的左下角顶点为整张图最左下角的点。

输入格式

第一行有用空格隔开的\(2\)个整数 \(m\) 和 \(n\),表示有 \(m \times n\) 个格子 \((1 \le m,n \le 50)\)。

接下来的 \(m\) 行,是一个 \(m \times n\) 的矩阵,每行有 \(n\) 个用空格隔开的整数,其中第 \(i\) 行第 \(j\) 列上的整数表示第 \(i\) 行第 \(j\) 列的格子上摞有多少个积木($1 \le $ 每个格子上的积木数 $ \le 100$)。

输出格式

输出包含题目要求的立体图,是一个 \(K\) 行 \(L\) 列的字符串矩阵,其中 \(K\) 和 \(L\) 表示最少需要 \(K\) 行 \(L\) 列才能按规定输出立体图。

样例 #1

样例输入 #1

3 4
2 2 1 2
2 2 1 1
3 2 1 2

样例输出 #1

......+---+---+...+---+
..+---+  /   /|../   /|
./   /|-+---+ |.+---+ |
+---+ |/   /| +-|   | +
|   | +---+ |/+---+ |/|
|   |/   /| +/   /|-+ |
+---+---+ |/+---+ |/| +
|   |   | +-|   | + |/.
|   |   |/  |   |/| +..
+---+---+---+---+ |/...
|   |   |   |   | +....
|   |   |   |   |/.....
+---+---+---+---+......

提示

NOIP2008普及组第四题

关于思路

有思路吗?
很明显没有
其实很简单,只要用一个二维字符数组存储下其形状即可。
怎么办到?
不会!
很好办,要做的,只不过是把各个正方体倒序存储下来(这样一来,遮挡的可直接覆盖),然后就可以了!(~ ̄▽ ̄)~ (当然,这需要打个小小的表)
诶,那"."怎么办?
简单!只要判断一下是否数组当前位置被修改过就好了啦!٩(๑>◡<๑)۶
如果没修改过,那这里一定是".",因为所有正方体的构成字符都遍历了一遍了嘛!
那要怎么实现只遍历正方体?
用个数组存存不就行了!
好吧,咱们,上代码?

步骤进行时

#include<cstdio>
using namespace std;
int m,n,a[1001][1001],maxx,maxy,z[6]={2,1,0,0,0,0},s[6]={6,6,6,6,5,4};
char c[1001][1001],c1[10][10]={
"  +---+",
" /   /|",
"+---+ |",
"|   | +",
"|   |/",
"+---+"};//打表( ̄▽ ̄)/

这里变量m,n就是图的规模,maxx,maxy是用来存储字符数组大小的,sz则用来控制遍历正方体构成。a是为高度,c是一直说的存答案的字符数组,c1用来打表。

void fg(int x,int y){//x,y为当前在字符数组的位置(左下角坐标)
	for(int i=5;i>=0;i--)//立方体需要倒过来存入数组 
		for(int j=z[i];j<=s[i];j++){//分别是这一行的宽度 
			c[5-i+x][j+y]=c1[i][j];//修改。有重叠会自动覆盖
			if(5-i+x>maxx) maxx=5-i+x;
			if(j+y>maxy) maxy=j+y;//分别记录最大长宽 
		}
}

用来求答案的函数(最关键的一步!)

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=0;j<m;j++)
			scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++)//层数 
		for(int j=0;j<m;j++)//列循环 
			for(int k=0;k<a[i][j];k++)//高度 
				fg((n-i)*2+1+3*k,(n-i)*2+1+4*j);//表示立方体左下角位置 
	for(int i=maxx;i>=1;i--){//因为倒序运算,所以也要倒序输出(maxx和maxy的用处)  
		for(int j=1;j<=maxy;j++)
			if(c[i][j]=='\0') printf(".");//为'\0',即未修改,也就是非正方体部分,要输出"."。 
			else printf("%c",c[i][j]);
		printf("\n");
	}
	return 0;
}

主函数

完整代码

#include<cstdio>
using namespace std;
int m,n,a[1001][1001],maxx,maxy,z[6]={2,1,0,0,0,0},s[6]={6,6,6,6,5,4};
char c[1001][1001],c1[10][10]={
"  +---+",
" /   /|",
"+---+ |",
"|   | +",
"|   |/",
"+---+"};
void fg(int x,int y){
	for(int i=5;i>=0;i--)
		for(int j=z[i];j<=s[i];j++){
			c[5-i+x][j+y]=c1[i][j];
			if(5-i+x>maxx) maxx=5-i+x;
			if(j+y>maxy) maxy=j+y;
		}
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=0;j<m;j++)
			scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++)
		for(int j=0;j<m;j++)
			for(int k=0;k<a[i][j];k++)
				fg((n-i)*2+1+3*k,(n-i)*2+1+4*j);
	for(int i=maxx;i>=1;i--){
		for(int j=1;j<=maxy;j++)
			if(c[i][j]=='\0') printf("."); 
			else printf("%c",c[i][j]);
		printf("\n");
	}
	return 0;
}

请注意

  • 要倒序存储,否则会造成覆盖失败导致乱象!(不要问我怎么知道的 ヽ(。>д<)p)
  • maxxmaxy很有用,循环时不用不行。
  • 字符不同于字符串,空的不是''!
  • 如果你拒绝使用zs,你的输出将不会有.

复杂度

由于一些特殊原因,无法把结果呈现给大家,在此附上网址:
https://www.luogu.com.cn/record/125943708
时间复杂度很低了,但空间稍微有点高(开了那么大数组嘛)

写在最后

没什么好写的了,只能说祝大家考试顺利!

THE END~

标签:maxy,积木,int,+---+,立体图,NOIP2008,verb,P1058
From: https://www.cnblogs.com/httony/p/17726222.html

相关文章

  • P1056 NOIP2008 普及组 排座椅
    \(P1056\)[\(NOIP2008\)普及组]排座椅题解先想一下算法:因为题目里出现了最优解,最好的方案关键字,所以一定会用贪心。然后从题目给的样例解释可以看到:如果相邻的两行有许多组说话的同学,那么在这两行中间加一条过道是非常划算的;同理,列也是如此。恍然大悟,只要找出划分哪些......
  • Lnton 羚通视频分析算法平台【OpenCV-Python】教程: Depth Map from Stereo Images 立
    立体图像的深度图(DepthMap)是表示图像中每个像素点距离相机的深度或距离信息的二维灰度图。它提供了场景中物体的三维结构和距离信息,对于三维重建、增强现实、虚拟现实等应用具有重要意义。深度图可以通过以下方式获取:1.双目视觉方法:使用两个相机(左右摄像机)同时拍摄同一场景,通过计......
  • 「NOIP2008 普及组」ISBN 号码 题解
    前言转自博客,早期黑历史作品。这是本蒟蒻の第一篇题解qwq,发在博客上,还请多多关照.这道题是一道橙题,难度没有太大的问题,对于大犇们来说自然是一遍过的,本蒟就只能调调再交了.题面传送门题目描述每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括99位数字、1......
  • P1056 [NOIP2008 普及组] 排座椅
    1.变量maxn和g在for循环内声明和初始化,是因为它们用于追踪每次循环中的最大值及其对应的索引。如果将maxn和g的声明移到for循环外部,它们将保留上一次迭代的值,并且比较语句if(a[j]>maxn)或if(b[j]>maxn)将无法正常工作。在每次迭代中将它们初始化为-1的目的......
  • SP10582 题解
    题目链接题意简述给定一个有\(n\)个数的数组,求从第一个数字开始,向后每\(k\)个数字的最大值。题目分析看到没有人用ST表做那我就来发一个吧。这道题可以用ST表做。它可以在经过\(O(N\logN)\)的预处理后,以\(O(1)\)的时间在线回答下标在\(l\)到\(r\)之间的数......
  • cdr软件怎么绘制立体图?cdr绘制立体图形的教程
    CorelDRAW的简称是cdr,是一款专业的矢量图绘制软件,一般都是用来绘制二维图形的,但是也可以绘制三维图形,下面内容就来用cdr软件演示绘制三维图形的教程cdr软件绘制三维图形的教程:进入CorelDRAW的操作界面,在左侧的工具箱列表中找到“椭圆形工具”,绘制出如图1所示的一个扁状椭圆形。图1:......
  • P1055 [NOIP2008 普及组] ISBN 号码
    [NOIP2008普及组]ISBN号码题目描述每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括$9$位数字、$1$位识别码和$3$位分隔符,其规定格式如x-xxx-xxxxx-x,其中符号-就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码......
  • 以圆类Circle及立体图形类Solid为基础设计圆锥类Cone
    以点类Point及平面图形类Plane为基类公有派生圆类Circle,再以圆类Circle及立体图形类Solid为基类公有派生圆锥类Cone,main(void)函数完成对圆锥类Cone的测试。Point类结构说明: Point类的数据成员包括:①私有数据成员:X坐标x(double型),Y坐标y(double型)。Point类成员函数包括:①......
  • 以圆类Circle及立体图形类Solid为基础设计圆柱类Cylinder
    以点类Point及平面图形类Plane为基类公有派生圆类Circle,再以圆类Circle及立体图形类Solid为基类公有派生圆柱类Cylinder,main(void)函数完成对圆柱类Cylinder的测试。Point类结构说明: Point类的数据成员包括:①私有数据成员:X坐标x(double型),Y坐标y(double型)。Point类成员函数......
  • 以圆类Circle及立体图形类Solid为基础设计圆锥类Cone
    以点类Point及平面图形类Plane为基类公有派生圆类Circle,再以圆类Circle及立体图形类Solid为基类公有派生圆锥类Cone,main(void)函数完成对圆锥类Cone的测试。Point类结构说明: Point类的数据成员包括:①私有数据成员:X坐标x(double型),Y坐标y(double型)。Point类成员函数包括:①......