赞
踩
【题目描述】
给出n(1<=n<=13),请输出一个直角边长度是n的数字直角三角形。
【样例输入】
5
【样例输出】
0102030405
06070809
101112
1314
15
【题目来源】
洛谷P5721 【深基4.例6】数字直角三角形
【解析】
本题的样例输出一眼望过去就是像一个矩阵,或者叫三角阵貌似更形象。我家娃断言,老师教过的,这种要使用一个x坐标、一个y坐标,因此要用两重循环。
看起来确实是这样:
①大循环:一行一行的输出,这是一种重复作业,可以用循环。
②小循环:一个数一个数的输出,后一个数是前一个数加1,这是一种有规律重复作业,可以用循环。
标准代码:
- #include<cstdio>
- using namespace std;
- int main(){
- int cnt=0, n;
- scanf("%d", &n);
- for(int i=1; i<=n; i++){
- for(int j=1; j<=n+1-i; j++){
- printf("%02d", ++cnt);
- }
- printf("\n");
- }
- return 0;
- }
代码中的i相当于y坐标,j相当于x坐标。本题的关键是要求出换行的位置,也就是每行中最后一个要输出的数的x坐标,即每行j的最大值j_max。
以n=5为例:
换行 | i | j_max | 规律 |
1 | 1 | 5 | 1+5=6 |
2 | 2 | 4 | 2+4=6 |
3 | 3 | 3 | 3+3=6 |
4 | 4 | 2 | 4+2=6 |
5 | 5 | 1 | 5+1=6 |
不难发现一个规律,i+j_max=6=5+1=n+1,即j_max=n+1-i。
但是老金看到这道题的第一感觉是应该可以用一层循环求解,当我提出这个想法时,却被我家娃一顿嘲笑。
他说老师教过,要用x坐标、y坐标。
只能感叹教育的僵化,希望老师们能意识到,教学生时尽量不要用“要”这个字,而应用“可以”、“也许”、“试试”之类的词。
之所以我认为可以用一层循环,主要是因为输出的数的规律是一致的,都是递增1,只不过要在不同的位置输出换行符。
所以,实现一层循环的难点依然是找到换行的位置。
因为只有一层循环,迭代的变量自然就是要输出的数。所以此时便没有了y坐标,就不能再用上表中与y坐标的和是固定值的规律了。
但是在上表中,单看j_max这一例也能一眼看出一个规律,就是值从n开始,每次递减1。咱们就可以利用这个规律实现一层循环。方法就是再引入一个累加器j++,每行开始输出时将其值置为0,当它累加到j_max的时候输出换行符。
代码如下:
- #include<stdio.h>
- int main(){
- int n, j=0;
- scanf("%d", &n);
- for(int i=1;;i++){
- j++;
- printf("%02d", i);
- if(j==n){
- printf("\n");
- n--;
- j=0;
- }
- if(n==0) break;
- }
- return 0;
- }
还有另外一个思路,就从输出的数中找出换行的位置,还是以n=5为例,假设输出的数为i。
换行 | i | 规律 |
1 | 5 | 0+5 |
2 | 9 | 5+4 |
3 | 12 | 9+3 |
4 | 14 | 12+2 |
5 | 15 | 14+1 |
每次输出换行符的位置都是上一个位置加上一个n--。代码如下:
- #include<stdio.h>
- int main(){
- int n, i_newline;
- scanf("%d", &n);
- i_newline=n;
- for(int i=1;;i++){
- printf("%02d", i);
- if(i==i_newline){
- printf("\n");
- n--;
- i_newline+=n;
- }
- if(n==0) break;
- }
- return 0;
- }
还有一点,上面两个一层循环的退出条件还可以直接设置在循环条件判断处。
for(int i=1;i<=n*(n+1)/2;i++)
想想为什么?
当然,此时代码中就不能随便改n的值了,即不能直接用n—了,而要先把n的值赋给另一个变量m,让m--。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。