洛谷——P1058 立体图

原题链接
一道有些复杂的模拟题。
核心思路是:先用字符数组储存一个正方体,然后按照从左到右,从下到上,从后向前的顺序一个一个摆上去。
这里有几个问题需要注意:
1.每一块正方体的坐标位置计算
2.第一个正方体的坐标位置

这里规定正方体的坐标是其左上顶点的坐标

对于其他正方体,仔细观察,很容易找到规律:从左向右时正方体行数和左边底部正方体的行数一致,列数加四;从下到上时列数与下方的正方体一致,行数减三。

每行第一个正方体行数与上一行相比要加二,列数满足规律2 * (M - m - 1) - 2,其中M是总行数,m是上一行的行数(从0开始枚举)。如果不理解,可以用代码跑一下m行n列,每个格的正方体数均为1的测试数据,仔细观察就能理解。

而第一个正方体的坐标处理略有些复杂。它的列坐标很容易确定2*M-2,但是行坐标与全局的正方体都有关。它的行坐标要保证最高的正方体行坐标刚好为0。根据这个思路很容易写出代码。

#include<iostream>
#include<climits>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;


int M, N;
// 记录要输出的行数和列数
int maxH, maxL;
// 储存正方体个数
int p[60][60];
char ans[500][200];
// 一个正方体
char cube[6][8] =
{
	{"..+---+"},
	{"./   /|"},
	{"+---+ |"},
	{"|   | +"},
	{"|   |/."},
	{"+---+.."}
};

// 在(i,j)坐标处绘制一个正方体,并同时记录最大的行列
void draw(int i, int j) {
	for (int ii = i, t = 0; t < 6; ii++, t++) {
		for (int jj = j, k = 0; k < 7; jj++, k++) {
			if (cube[t][k] != '.') {
				ans[ii][jj] = cube[t][k];
				maxH = max(maxH, ii);
				maxL = max(maxL, jj);
			}
		}
	}

}

int main()
{
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> M >> N;
	// 先全部设为.
	for (int i = 0; i < 200; i++) {
		for (int j = 0; j < 200; j++) {
			ans[i][j] = '.';
		}
	}

// 记录每行正方体个数最大值
	for (int m = 0; m < M; m++) {
		for (int n = 0; n < N; n++) {
			cin >> p[m][n];
			p[m][N] = max(p[m][N], p[m][n]);
		}
	}

// startx starty 是第一个正方体的位置坐标
// 先让其在第0行满足最高的正方体行数为0
// 然后枚举每一行,不断修改startx的值
	int starty = 2 * M - 2, startx = (p[0][N] - 1) * 3;
	for (int m = 0; m < M; m++) {
		int mx = startx + m * 2 - (p[m][N] - 1) * 3;
		if (mx < 0)
			startx -= mx;
	}
	// 绘图 这个不再多讲 自己找找规律吧
	for (int m = 0; m < M; m++) {
		for (int n = 0; n < N; n++) {
			int num = 0;
			while (p[m][n]--) {
				draw(startx - num * 3, starty);
				num++;
			}
			starty += 4;
		}
		starty = 2 * (M - m - 1) - 2;
		startx += 2;
	}

	for (int i = 0; i <= maxH; i++) {
		for (int j = 0; j <= maxL; j++) {
			cout << ans[i][j];
		}
		cout << endl;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值