zoukankan      html  css  js  c++  java
  • 字符三角形系列——数列与函数变换

    一、准备知识

      1:根据数列的前有限项归纳通项公式(主要是直线型),也可以说是一次函数的运用。

      2:坐标平移。把函数y=f(x)的图像向右平移m个单位可得到y=f(x-m)的图形,把函数y=f(x)的图像向上平移n个单位可得到函数y=f(x)+n的图像

      3:对称变换。把函数y=f(x)的图像沿直接x=m对称可得到函数y=f(2m-x)的图像,把函数y=f(x)的图像沿y=n对称后可得到2n-y=f(x)的图像

      4:翻折变换。把函数y=f(x)的图像中y轴左边部分清除,把右边图像沿y轴对称到左边,右边图像依然保留,把函数y=f(x)的图像中x轴下边部分清除,把上边图像沿x轴对称到下边,上边图像依然保留

    二、字符三角形示例

    1:输出下图字符三角形,其中字符可变,行数也可变。

    *
    **
    ***
    ****
    *****
    ******

      本例较为简单,首先确定行数,逐行输出——一个循环可解决。每一行的字符个数在变,容易看出跟行数有关——就等于行号,故而整个输出就一个双循环可搞定,代码如下

    #include<iostream>
    using namespace std;
    int main(){
        int a=6;
        char ch='*';
        for(int y=1;y<=a;y++)
        {
            for(int x=1;x<=y;x++)
                cout<<ch;
            cout<<endl;
        }
        return 0;
    }
    square1

     2:输出下图字符三角形

    ******
    *****
    ****
    ***
    **
    *

      这个问题跟上一个问题类似,只是每一行的字符个数逆序而己。实现方法就是改变内循环总次数,而这个次数其实就是一个关于行号的函数,也可以说是一个数列的通项公式。当然也可是跟第一个问题类似的处理办法,只是一个取前段,一个取后段。两个思路的代码如下

    #include<iostream>
    using namespace std;
    int main(){
        int a=6;
        char ch='*';
        for(int y=1;y<=a;y++)
        {
            for(int x=y;x<=a;x++)
                cout<<ch;
            cout<<endl;
        }
        return 0;
    }
    square2-1
    #include<iostream>
    using namespace std;
    int main(){
        int a=6;
        char ch='*';
        for(int y=1;y<=a;y++)
        {
            for(int x=1;x<=a+1-y;x++)
                cout<<ch;
            cout<<endl;
        }
        return 0;
    }
    square2-2

    3:输出下图字符三角形

         *
        **
       ***
      ****
     *****
    ******

      这个问题可以做个分解,每行分两个部分,前部分是空格,后部分是字符,空格个数参照第二个问题,字符个数参照第一个问题,代码实现应该较为容易。还有一种思路,把整个输出看作是一个aXa方阵,找出空格与字符的分界,用条件判断是输出字符还是空格。为了符合习惯,我们可以把行号转换成纵坐标,把整个分界线看作一个函数的图像(部分)。代码如下

    #include<iostream>
    using namespace std;
    int main(){
        int a=6;
        char ch='*';
        for(int y=1;y<=a;y++)
        {
            for(int x=y+1;x<=a;x++)
                cout<<' ';
            for(int x=1;x<=y;x++)
                cout<<ch;
            cout<<endl;
        }
        return 0;
    }
    square3-1
    #include<iostream>
    using namespace std;
    int main(){
        int a=6,x,y;
        char ch='*';
        for(int i=1;i<=a;i++)
        {
            y=a+1-i;//用于转换坐标系 
            for(x=1;x<=a;x++)
            {
                if(y>x)cout<<' ';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square3-2

    4:输出下图字符三角形

         *
        ***
       *****
      *******
     *********
    ***********

      按照前面的经验,如果把每一行分成两个部分,那这个问题也不难,前面是空格,跟第三个问题差不多,字符个字数嘛,不难看出就是奇数,其通项公式很容易得出第n行的个数是2n-1。

      当然也可以看作第一个问题的图像沿y轴翻折而成,根据前面所述,每一行的数字可以是-a到a。如果不喜欢负数,也可以向右平移a单位,其代码如下

    #include<iostream>
    using namespace std;
    int main(){
        int a=6;
        char ch='*';
        for(int y=1;y<=a;y++)
        {
            for(int x=y+1;x<=a;x++)
                cout<<' ';
            for(int x=1;x<=y*2-1;x++)
                cout<<ch;
            cout<<endl;
        }
        return 0;
    }
    square4-1
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=5,x,y;
        char ch='*';
        for(int i=0;i<=a;i++)
        {
            y=a+1-i;//用于转换坐标系 
            for(x=-a;x<=a;x++)
            {
                if(y>a+1-abs(x))cout<<' ';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square4-2
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=5,x,y;
        char ch='*';
        for(int i=0;i<=a;i++)
        {
            y=a+1-i;//用于转换坐标系 
            for(x=0;x<=a*2;x++)
            {
                if(y>a+1-abs(x-a))cout<<' ';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square4-3

    5:输出下图字符三角形

          *
         ***
        *****
       *******
      *********
     ***********
     ***********
      *********
        *******
         *****
          ***
           *

      这个问题可以分上下两部分,这个方法就不再做了,我们完全可以做上下翻折变换,当然也可以通过平移稍做改变,实现代码如下

    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=6,x,y;
        char ch='*';
        for(int i=-a;i<=a;i++)
        {
            y=abs(i);
            for(x=0;x<y;x++)
                cout<<' ';
            for(x=1;x<=(a-y)*2+1;x++)
                cout<<ch;
            cout<<endl;
        }
        return 0;
    }
    square5-1
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=5,x,y;
        char ch='*';
        for(int i=-a;i<=a;i++)
        {
            y=abs(i);//用于转换坐标系 
            for(x=-a;x<=a;x++)
            {
                if(y>a-abs(x))cout<<' ';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square5-2
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=5,x,y;
        char ch='*';
        for(int i=0;i<=a*2;i++)
        {
            y=abs(a-i);//用于转换坐标系 
            for(x=0;x<=a*2;x++)
            {
                if(y>a-abs(x-a))cout<<' ';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square5-3

    6:输出以下图像

         *         *
        ***       ***
       *****     *****
      *******   *******
     ********* *********
    *********************

      这个例子可以说简单,就是把第四个示例的图像对称一下就好,你知道对称轴吗?代码如下

    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=5,x,y;
        char ch='*';
        for(int i=0;i<=a;i++)
        {
            y=a-i;//用于转换坐标系 
            for(x=-2*a;x<=a*2;x++)
            {
                if(y>a-abs(abs(x)-a))cout<<' ';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square6-1
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=5,x,y;
        char ch='*';
        for(int i=0;i<=a;i++)
        {
            y=a-i;//用于转换坐标系 
            for(x=0;x<=a*4;x++)
            {
                if(y>a-abs(abs(a*2-x)-a))cout<<' ';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square6-2

    7:输出以下图像

      这个示例只是用了两个字符,形成中间的两个菱形字符,可以是第6个示例的纵向翻折,也可以是第5个示例的横向对称,代码如下

    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=6,x,y;
        char ch='O';
        for(int i=0;i<=a*2;i++)
        {
            y=abs(a-i);//用于转换坐标系 
            for(x=-2*a;x<=a*2;x++)
            {
                if(y>a-abs(abs(x)-a))cout<<'H';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square7-1
    #include<iostream>
    #include<cmath>
    using namespace std;
    int main(){
        int a=6,x,y;
        char ch='+';
        for(int i=0;i<=a*2;i++)
        {
            y=abs(a-i);//用于转换坐标系 
            for(x=0;x<=a*4;x++)
            {
                if(y>a-abs(abs(a*2-x)-a))cout<<' ';
                else cout<<ch;
            }
            cout<<endl;
        }
        return 0;
    }
    square7-2

      小结:算法终究是离不开数学的,好的算法是建立在好的数学思维之上的,开动脑筋,不僵化就会有好的算法。以上内容仅供参考,如有不妥请指教。

  • 相关阅读:
    滑动窗口法与剑指offer:和为S的连续正数数列 与 和为S的两个数字
    数组中的逆序对与归并中的分治思想
    重读STL源码剖析:迭代器
    重读深度探索C++对象模型:函数
    FreeMarker笔记 前言&第1章 入门
    分享我的PL/SQL的优化设置,为开发全面提速
    迅影QQ视频查看v2.0 源码
    Invalid encoding name "UTF8". 报错 XML
    [HNOI2003]消防局的设立
    We need water!
  • 原文地址:https://www.cnblogs.com/wendcn/p/13445556.html
Copyright © 2011-2022 走看看