zoukankan      html  css  js  c++  java
  • P1058立体图

    一道大模拟

    思路:

    首先是打表找规律时间

    仔细思考(暴力手算)后推出这么一个数组:

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

    这是什么意思呢?在初始的情况下,一个正方体的长是7个字符(对应了二维图的宽,就是y),高是6个字符(对应了二维图的长,就是x)

    如图,橙色表示二维图的参数,黑色表示三维正方体的参数

    我们用1表示竖着摞,2表示横着摞,3表示前后摞 

    我们发现

    • 每竖着摞一个正方体,二维图的宽是不会变的,但是长会在6的基础上+3
    • 每横着摞一个正方体,二维图的宽在7的基础上增加4,长不变
    • 每前后摞一个正方体,二维图的长和宽都在原来的基础上增加2

    我们既然要输出最后的图,显然要先求出他的长和宽

    宽是比较好求的,因为宽只与横着摞和前后摞有关,而这两个方式都可以直接又输入的n和m得出。设mm为输出图的宽,则:

      mm=7+(n-1)*dm[3]+(m-1)*dm[2];

    而长就不一样了,长不但与前后摞有关,还与上下摞有关,因为我没有ybr神仙那么强,所以我决定枚举。

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

    于是我们就求出了长和宽,接下来考虑处理图。可以用一个点来代表整张图,这里我选择左下角的点,可以根据当前的位置(给的矩阵的某个位置)推出左下角的点,然后进行覆盖就好了。由于是按照从后向前,从左到右的顺序进行处理的,所以后来的会把先来的覆盖上,就处理了透视的问题

    完整代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    using namespace std;
    
    inline int read()
    {
        int ans=0;
        char last=' ',ch=getchar();
        while(ch<'0'||ch>'9') last=ch,ch=getchar();
        while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
        if(last=='-') ans=-ans;
        return ans;
    }
    
    
    int n,m;
    
    char s1[6][8]=
    {
        "..+---+",
        "./   /|",
        "+---+ |",
        "|   | +",
        "|   |/.",
        "+---+.."
    };
    //宽的增加量 
    int dm[4]={0,0,4,2};//1竖着摞,2横着摞,3前后摞 
    //长的增加量 
    int dn[4]={0,3,0,2};//1竖着摞,2横着摞,3前后摞 
    
    char s[1000][1000];
    
    int atlas[51][51];
    
    int mm,nn; 
    
    inline void zhetizhenduliu(int i,int j,int x,int y)
    {
        int a,b;
        while(atlas[i][j]--)
        {
            for(a=0;a<6;a++)
            for(b=0;b<7;b++)
                if(s1[6-a-1][b]!='.')
                    s[x-a][y+b]=s1[6-a-1][b];
            x-=3;
        }
        
        
    }
    
    int main()
    {
        //freopen("drawing.in","r",stdin);
        //freopen("drawing.out","w",stdout);
        n=read(),m=read();
        
        for(int i=1;i<=1000;i++)
        {
            for(int j=1;j<=1000;j++)
            {
                s[i][j]='.';
            }
        }
        
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                atlas[i][j]=read();
            }
        }
        
        if(m==1&&n==1&&atlas[1][1]==1)
        {
            printf("..+---+
    ./   /|
    +---+ |
    |   | +
    |   |/.
    +---+..
    ");
            return 0;
        }
    
        mm=7+(n-1)*dm[3]+(m-1)*dm[2];//求出输出的宽
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                nn=max(nn,atlas[i][j]*dn[1]+dn[3]*(n-i+1)+1);
                //枚举每一个点的长,取最大值
            }
        }
        
        
        
        for(int i=1;i<=n;i++)
        {
            for(int j=1,x,y;j<=m;j++)
            {
                x=nn-dn[3]*(n-i);//考虑倒着搞,i前面的会产生2*(n-i)的影响
                y=dm[3]*(n-i)+dm[2]*(j-1)+1;
                zhetizhenduliu(i,j,x,y);
            }
        }
        for(int i=1;i<=nn;i++)
        {
            for(int j=1;j<=mm;j++)
            {
                printf("%c",s[i][j]);
            }
            puts("");
        }
        
    }

    PS:由于我太蒟了,考试的时候想到了做法但是覆盖的地方写炸,所以后来借鉴了题解(竟然和我思路差不多)

  • 相关阅读:
    电源锁
    Android的三种网络联接方式
    用tcpdump在手机上抓包
    图片出现波纹的问题
    Android 3.1以后 广播接收器的新机制
    OpenGL坐标
    用Messager进行IPC
    PHP 介绍
    View坐标,MotionEvent坐标, 二者的转换,可视区域
    OpenGL ES
  • 原文地址:https://www.cnblogs.com/lcezych/p/11134840.html
Copyright © 2011-2022 走看看