立体图【题目链接】

然后因为有点(不是有点,非常)懵,因此我只能看一步写一步。

首先总体思路:

将三维立体图看做二维平面图,先确定出二维图的长和宽,然后,按照三维立体图的透视顺序,从最后一排的最左开始依次覆盖操作,直到覆盖完成,不用的地方填‘.’;

首先是处理二维图的长和宽:

(首先要说的是,以下所有长均指竖向,宽均为横向)

经过画图找规律我们了解到了对于一个方块,如果我们在它上面增加一个方块,对于这个方块和新增的方块的某个对应点来说,长增加了3,宽增加0;:

对应点用不同颜色标出;

然后对于前后摆放的情况:

从图中可以看出,长增加了2,宽增加了2;

然后对于左右摆放的情况:

由图中可以看出,长莫得增加,宽增加了4;

然后对应以下数组:

//宽的增加量
int dm[4]={0,0,4,2};//1竖着摞,2横着摞,3前后摞
//长的增加量
int dn[4]={0,3,0,2};//1竖着摞,2横着摞,3前后摞

然后我们求一下我们要存的二维平面的大小:

对于横放的宽:从最左下角开始计算,先计算

中,最右下的位置(图中红圈内紫色点的位置);

=(m-1)*dm[2]+5(首先第一个方块占了5个单位,然后剩余的m-1个方块,每放一个,增加4个单位)

计算完成后,再计算

中剩余位置也就是红圈‘+’所在位置,如何计算剩下的长度呢,我们需要用到前后摆放的增加量:还是同样,首先先把第一个方块单列,这个方块的(右面吧)为宽提供了3的价值(但是要注意的是,因为第一个方块最左下的贡献与上面的计算重复了,所以实际我们只需要+2),剩余n-1个方块,每个为宽提供了2个价值。

因此宽mm=5+(m-1)*dm[2]+(n-1)*dm[3]+2;

再来看长,因为lz看的题解的博主:小蒟蒻皮皮鱼(友情安利,这是个大佬)他自己说他比较菜,用的枚举的方法,lz也只看懂了枚举的方法:

for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
nn=max(nn,atlas[i][j]*dn[]+dn[]*(n-i+)+);
//枚举每一个点的长,取最大值

同样算最高的,先算出:atlas[i][j]*dn[1]+1(其中atlas为输入的矩阵数据),算出的是粉线部分,然后(n-i+1)这个表示的是第几排(因为数组是:↓→这样存储的,但是实际上我们要画的是↑→的图,因此要减一下)对于第(n-i+1)排,它的上面对长的贡献就是dn[3]*(n-i+1)(这里不再加一是因为有一个点前面和上面都有贡献,我们只需要加一次(绿点处)),也就是每个方块对长贡献2;(当然要枚举取最高的)

然后考虑一张图,我们按照透视的顺序,从后往前,从左往右的依次添加覆盖,首先是最左下的立方体(其实一般会被全部覆盖掉,但我们还是要加),然后我们固定一个点,为立方体的定位点,以此点为基础拓展出整个立方体,所以最关键的一点就是定位立方体了:

这里定位立方体的左下角:

然后就是咋的定位了,

然后我们还是看个样例:(啊算了,我补不出来(艰难))

(百度网图qwq)

然后你看这个图,输入的数据中为atlas[1][1]的立方体的左下角就是红点标出的地方,然后我们求出的nn是绿色线标出的地方,mm是紫色线标出的地方,这样我们在存二维数组时,先存最左下角的立方体:

求某个立方体左下角坐标:

对于x(与nn(长)同方向的那个),我们显然只需要考虑dn对其的影响;(上下)

然后因为我们的思路是:

求出红点的在二维平面的坐标,然后给对于每个立方体上面再摞立方体。

所以不用把层数>=2的左下角求出来;

回到这个图:

我们应该如何求这个点的x呢??

先放代码(因为发现莫得代码不知道咋的讲):

 for(int i=;i<=n;i++){
for(int j=,x,y;j<=m;j++){
x=nn-dn[]*(n-i);
y=dm[]*(n-i)+dm[]*(j-)+;
zhetizhenduliu(i,j,x,y);
}
}

根据我们楼上的经验,对于每一横行来说,每向后放置一个立方体,对应点的x就会+dn[3],因此我们在计算x时,考虑这个立方体相对于第一排立方体向后挪了几个,因为数组atlas[1][i]其实对应的是最后一行,所以我们覆盖是从1↓m,1→n。(n-i)表示的就是我们从第一行向后放了几个立方体到达了我们当前要放立方体的这一行,楼上红点就是3-1,表示我们在放这个方块之前已经放了两个方块,每放一个方块,x就要相对于绿线 所在地方向后dn[3](2)个,因为绿线是最大的位置,所以实际我们需要用nn-(n-i)*dn[3];

然后对于y(与mm方向相同)(宽)

啊又要画图

还是先推第一排的立方体,假设j=2(先不管i了在这不重要)

那么很显然这个点首先要计算的还是第一排的位置,也就是(j-1)*dm[2]+1(每左右放一个方块增加4,因为我们求的是左下角,所以不能用j乘而是要用(j-1)乘(然后别忘了+1)。

然后再算前后摆放造成的影响,也是同样,对于前后摆放,每摆放一个,左下角的位置向右挪2,然后也是从后往前记得编号嘛,所以还是要用(n-i)*dm[3];

然后定位好了左下角,我们可以尝试开始覆盖了:

inline void zhetizhenduliu(int i,int j,int x,int y){
//x,y表示我们定位点的左下角坐标,i,j表示我们定位点应该是输入矩阵的哪一个坐标;
int a,b;
while(atlas[i][j]--){
for(a=;a<;a++)
for(b=;b<;b++)
if(s1[-a-][b]!='.')
s[x-a][y+b]=s1[-a-][b];
x-=;
}
}

然后忘记讲的一件事,我们要先将立方体打好表:

char s1[][]=
{
"..+---+",
"./ /|",
"+---+ |",
"| | +",
"| |/.",
"+---+.."
};//真好看的说

然后你看这是个6*7的表,但开了6*8,你开6*7会炸,因为对于字符串, 除了你存的字符外,它会再存入一个我也忘了叫啥的某个东西,因此我们要多开一个;

然后覆盖:

首先要讲的是,我们只计算了最底层的立方体的左下角位置,然后是向上摞立方体,当我们每向上摞一个立方体时,长就 -=3;(因为我们输出是从上往下输出,所以越靠近输出的最上方的立方体的长其实越小,也就是需要 -=3而不是+=3的原因)这是最外层while循环;

我们计算出来的(x,y)实际上对应到s1数组中是s1[6][0];

用s数组存最终覆盖后的答案,那么注意要判断的是s1[i][j](表示s1数组中某一个位置)!='.'或许你会像我一样开始时认为没什么用,但是如果你不加这一句:

你就wa声一片了;

注意的是,这里s数组是从1开始存的,而s1数组是从0开始存的;

然后应该可以理解的吧,因为我们定位的是左下角,所以对于其他任意一个点,都可以由左下角的点的坐标加加减减得出,而且对于长,一定是减,对于宽,一定是加(加减均包括0),然后就枚举就好啦;

附上ych小蒟蒻皮皮鱼的神仙代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std; inline int read() {
int ans=;
char last=' ',ch=getchar();
while(ch<''||ch>'') last=ch,ch=getchar();
while(ch>=''&&ch<='') ans=(ans<<)+(ans<<)+ch-'',ch=getchar();
if(last=='-') ans=-ans;
return ans;
} int n,m; char s1[][]= {
"..+---+",
"./ /|",
"+---+ |",
"| | +",
"| |/.",
"+---+.."
}; int dm[]= {,,,};
int dn[]= {,,,};
char s[][];
int atlas[][];
int mm,nn; inline void zhetizhenduliu(int i,int j,int x,int y) {
int a,b;
while(atlas[i][j]--) {
for(a=; a<; a++)
for(b=; b<; b++)
if(s1[-a-][b]!='.')
s[x-a][y+b]=s1[-a-][b];
x-=;
}
} int main() { n=read(),m=read(); for(int i=; i<=; i++)
for(int j=; j<=; j++)
s[i][j]='.'; for(int i=; i<=n; i++)
for(int j=; j<=m; j++)
atlas[i][j]=read(); mm=+(n-)*dm[]+(m-)*dm[];
for(int i=; i<=n; i++)
for(int j=; j<=m; j++)
nn=max(nn,atlas[i][j]*dn[]+dn[]*(n-i+)+); for(int i=; i<=n; i++) {
for(int j=,x,y; j<=m; j++) {
x=nn-dn[]*(n-i);
y=dm[]*(n-i)+dm[]*(j-)+;
zhetizhenduliu(i,j,x,y);
}
}
for(int i=; i<=nn; i++) {
for(int j=; j<=mm; j++) {
printf("%c",s[i][j]);
}
puts("");
}
return ;
}

end-

【洛谷p1058】立体图(已完结)的更多相关文章

  1. 如何求先序排列和后序排列——hihocoder1049+洛谷1030+HDU1710+POJ2255+UVA548【二叉树递归搜索】

    [已知先序.中序求后序排列]--字符串类型 #1049 : 后序遍历 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho在这一周遇到的问题便是:给出一棵二叉树的前序和 ...

  2. 洛谷 P6672 - [清华集训2016] 你的生命已如风中残烛(组合数学)

    洛谷题面传送门 题解里一堆密密麻麻的 Raney 引理--蒟蒻表示看不懂,因此决定写一篇题解提供一个像我这样的蒟蒻能理解的思路,或者说,理解方式. 首先我们考虑什么样的牌堆顺序符合条件.显然,在摸牌任 ...

  3. [洛谷OJ] P1114 “非常男女”计划

    洛谷1114 “非常男女”计划 本题地址:http://www.luogu.org/problem/show?pid=1114 题目描述 近来,初一年的XXX小朋友致力于研究班上同学的配对问题(别想太 ...

  4. 洛谷P3372 【模板】线段树 1

    P3372 [模板]线段树 1 153通过 525提交 题目提供者HansBug 标签 难度普及+/提高 提交  讨论  题解 最新讨论 [模板]线段树1(AAAAAAAAA- [模板]线段树1 洛谷 ...

  5. 洛谷P1294 高手去散步

    洛谷1294 高手去散步 题目背景 高手最近谈恋爱了.不过是单相思.“即使是单相思,也是完整的爱情”,高手从未放弃对它的追求.今天,这个阳光明媚的早晨,太阳从西边缓缓升起.于是它找到高手,希望在晨读开 ...

  6. 洛谷P1220 关路灯

    洛谷1220 关路灯 题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关 ...

  7. 洛谷 P1656 炸铁路

    P1656 炸铁路 题目提供者kkksc03 标签图论搜索/枚举洛谷原创 难度普及/提高- 题目描述 因为某国被某红色政权残酷的高压暴力统治.美国派出将军uim,对该国进行战略性措施,以解救涂炭的生灵 ...

  8. 洛谷 P3384 【模板】树链剖分

    树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...

  9. 洛谷 P3410 拍照

    洛谷 P3410 拍照 题目描述 小B有n个下属,现小B要带着一些下属让别人拍照. 有m个人,每个人都愿意付给小B一定钱让n个人中的一些人进行合影.如果这一些人没带齐那么就不能拍照,小B也不会得到钱. ...

随机推荐

  1. HGOI20190809 省常中互测2

    Problem A 时之终结 构造一个含有$n$个节点的无重边无自环的有向图, 使得从$1$出发,每一次经过一条$(u,v) (u < v)$的边到达节点$n$的方案恰好有$y$种. 对于$10 ...

  2. Springboot 使用JPA

    Springboot 使用jpa maven依赖 <dependency> <groupId>org.springframework.boot</groupId> ...

  3. 'vue' 不是内部或外部命令,也不是可运行的程序 或批处理文件

    解决方案:找到npm i xxx -g 下载后存放的路径,将路径添加到环境变量中,即可.1.npm config list 查看一下npm 的配置信息 2.打开路径看看里面的命令.window用户wi ...

  4. TCP序列号和确认号

    TCP序列号和确认号详解 在网络分析中,读懂TCP序列号和确认号在的变化趋势,可以帮助我们学习TCP协议以及排查通讯故障,如通过查看序列号和确认号可以确定数据传输是否乱序.但我在查阅了当前很多资料后发 ...

  5. Keil工程Lib库文件的制作和运用

    最近看了百度手环开源项目,发现所有的算法都被封装成了一个lib文件在keil中调用 也是第一次学习到. 问题引出:为什么要做成lib库? 1.有些方案公司为了将自己写的关键部分源代码不进行公开,但是同 ...

  6. Windows下如何安装Redis

    Redis可以从下面的github上面下载,当前的下载版本为3.2.100版本 https://github.com/MicrosoftArchive/redis/releases 这边都是64位的链 ...

  7. mysql 查询一个月的数据

    //今天 select * from 表名 where to_days(时间字段名) = to_days(now()); //昨天 SELECT * FROM 表名 WHERE TO_DAYS( NO ...

  8. Boost学习

    使用boost function使用类成员函数作为回调函数 #include <iostream> #include <boost/function.hpp> struct M ...

  9. Spring Boot中使用 Thymeleaf

    目录 1.pom.xml引入thymeleaf 2.关闭缓存application.properties 3.编写Controller类 4.模板html 5.运行结果 1.pom.xml引入thym ...

  10. MYSQL中唯一约束和唯一索引的区别

    1.唯一约束和唯一索引,都可以实现列数据的唯一,列值可以有null.2.创建唯一约束,会自动创建一个同名的唯一索引,该索引不能单独删除,删除约束会自动删除索引.唯一约束是通过唯一索引来实现数据的唯一. ...