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

    1149 立体图

     

    2008年NOIP全国联赛普及组

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 钻石 Diamond
     
     
    题目描述 Description

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

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

      +---+

     /   /|  高

    +---+ |

    |   | +

    |   |/ 宽

    +---+

     长

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

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

    ..+---+---+

    ./   /   /|

    +---+---+ |

    |   |   | +

    |   |   |/.

    +---+---+..

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

    ..+---+

    ./   /|

    +---+ |

    |   | +

    |   |/|

    +---+ |

    |   | +

    |   |/.

    +---+..

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

    ….+---+

    …/   /|

    ..+---+ |

    ./   /| +

    +---+ |/.

    |   | +..

    |   |/…

    +---+….

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

    输入描述 Input Description

    输入文件drawing.in第一行有用空格隔开的两个整数m和n,表示有m*n个格子(1<=m,n<=50)。

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

    输出描述 Output Description

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

    样例输入 Sample Input

    3 4

    2 2 1 2

    2 2 1 1

    3 2 1 2

    样例输出 Sample Output

    ......+---+---+...+---+

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

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

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

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

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

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

    |    |   | +-|    | + |/.

    |    |   |/  |    |/| +..

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

    |    |   |    |   | +....

    |    |   |    |   |/.....

    +---+---+---+---+......

    数据范围及提示 Data Size & Hint
     

    题解:(其实我也没太读懂这所谓"普及组"的题目,那就先这样模拟吧)

    这道题实际上是利用了立体几何的透视原理 
    我们可以从后面往前画 
    这是一种非常奇怪的方法 
    但是却非常有效

    我们可以先写一个函数 
    画一个立方体

    void deal(int x,int y){
        for(int i=y+1;i<y+4;i++)
            p[x][i]=p[x-3][i]=p[x-5][i+2]='-';
        for(int i=x-1;i>x-3;i--)
            p[i][y]=p[i][y+4]=p[i-2][y+6]='|';
        for(int i=x-1;i>x-3;i--)
            for(int j=y+1;j<y+4;j++)
                p[i][j]=' ';
        for(int i=x-2;i>x-4;i--)
            p[i][y+5]=' ';
        for(int i=y+2;i<y+5;i++)
            p[x-4][i]=' ';
        p[x][y]=p[x-3][y]=p[x][y+4]=p[x-3][y+4]='+';
        p[x-4][y+1]=p[x-4][y+5]=p[x-1][y+5]='/';
        p[x-5][y+2]=p[x-5][y+6]=p[x-2][y+6]='+';
    }

    其实这一步是十分好想的 
    自己画图就能想出来 
    接下来是计算长度和宽度

    经过我个人运算

    w=4*n+2*m+1;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            h=max(h,H[i][j]*3+3+2*(m-i));

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    #define N 51
    int n,m,w,h,H[N][N];
    char p[N*20][N*20];
    inline void deal(int x,int y){
        for(int i=y+1;i<y+4;i++)
            p[x][i]=p[x-3][i]=p[x-5][i+2]='-';
        for(int i=x-1;i>x-3;i--)
            p[i][y]=p[i][y+4]=p[i-2][y+6]='|';
        for(int i=x-1;i>x-3;i--)
            for(int j=y+1;j<y+4;j++)
                p[i][j]=' ';
        for(int i=x-2;i>x-4;i--)
            p[i][y+5]=' ';
        for(int i=y+2;i<y+5;i++)
            p[x-4][i]=' ';
        p[x][y]=p[x-3][y]=p[x][y+4]=p[x-3][y+4]='+';
        p[x-4][y+1]=p[x-4][y+5]=p[x-1][y+5]='/';
        p[x-5][y+2]=p[x-5][y+6]=p[x-2][y+6]='+';
    }
    int main(){
        cin>>m>>n;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                cin>>H[i][j];
        w=4*n+2*m+1;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                h=max(h,H[i][j]*3+3+2*(m-i));
        for(int i=1;i<=h;i++)
            for(int j=1;j<=w;j++)
                p[i][j]='.';
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=H[i][j];k++)
                    deal(h-2*(m-i)-3*(k-1),4*(j-1)+1+(m-i)*2);
        for(int i=1;i<=h;i++){
            for(int j=1;j<=w;j++)
                cout<<p[i][j];
            cout<<endl;
        }
        return 0;
    }
  • 相关阅读:
    程序员的九重境界,你是第几重?
    一个常用的正则表达验证类(转载)
    学习程序设计的态度
    科技期刊学术不端文献检测系统(转载)
    用GridView设计固定行数的入库单报表
    JavaScript技巧集
    线程的概念
    java实验三 类的继承与多态
    常见的网络攻击手段及防御方法
    类和对象的概念(转载)
  • 原文地址:https://www.cnblogs.com/shenben/p/5653698.html
Copyright © 2011-2022 走看看