PTA练习集L1-002之打印沙漏

简单记录下这道题目貌似只通过了一个测试点。然后今天再修改了下,第二个测试点没过,后来知道是因为没分情况(输入个数n>=7n<7),最后通过了。但是我发现我的代码依然不完全正确的,因为对某些个数的点输出的剩余个数是不对的,但我不知道为什么能通过,也不知道为什么输出剩余个数不对T-T,要是知道的同学希望可以解决一下我的疑惑,或者等我知道后再修改博文或者放评论区。

(最底下有更新!!!)

题目:

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

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

所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。

给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。

输入格式:

输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。

输出格式:

首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。

输入样例:

19 *

输出样例:

*****
 ***
  *
 ***
*****
2

 我的代码:

#include<iostream>
using namespace std;
int main(){
	int n,i,floor=0,result=0;  //n为个数,i是记录下点数最多的那一层的点数(第一层和倒数第一层的点数),floor是记录下从有效层数(第1层到最中间一层的上一层)
	char ch;
	cin>>n>>ch;
	int sum=n;
	int half=(n-1)/2;
	if(n>7){
		for(i=1;half>i;){
			i+=2;
		    floor++;
			half-=i;
		}
		int s=i;
		for(int k=0;k<floor+1;k++){  //记录下剩余点数,由于中间一层的点数1也要加上,故使floor+1
			if(s==1){
				sum-=1;
			}
			else{
				sum-=s*2;
			}
			s-=2;
		}
		int sign=i;
		int Nn;
		int nn=0,N=nn;     //N、nn代表应有的空格数量
		for(i=0;i<floor;i++){
			while(nn>0){   //当要输出nn个空格时则输出空格
				cout<<" ";
				nn--;
			}
			for(int j=0;j<sign;j++){
				cout<<ch;   //然后打印标点
			}
			cout<<endl;
			sign-=2;   //每打印完一层时点数-2,则是下一层该打印的点数
			nn++;
			N++;   //N记录的是下一层该有的空格数,(如最开始N=0,第一次进行N++表示第二层该要有1个空格,然后用N更新nn
			nn=N;
		}
		if(N>0){
			for(i=0;i<N;i++){
				cout<<" ";
			}
		}
		for(i=0;i<sign;i++){
			cout<<ch<<endl;
		}
		sign+=2;   //由于打印完中间一层,中间一层的下一层较之多了俩点数,故s+=2
		N--;    //下一层的空格数较中间一层的空格数少1
		int NN=N;   //这里的NN作用相当于上述的N
		for(i=0;i<floor;i++){
			while(N>0){
					cout<<" ";
				N--;
			}
			for(int j=0;j<sign;j++){
				cout<<ch;
			}
			cout<<endl;
			sign+=2;
			N--;
			NN--;
			N=NN;
		}
		cout<<sum<<endl;
		}
	else{
		cout<<ch<<endl;
		cout<<n-1<<endl;
	}
	
}

这是测评结果:

但是!!!对于一些其他数量的点:

 奇奇怪怪,我尽力找出问题所在......

----------------------------------------------------------(分割线)------------------------------------------------------------

(更新!!!)只是更新代码依然不知道pta为什么会通过上面的代码

在我把这篇文章存入草稿箱之后,我又在编译器里看到了关于这个题目的没写完的代码,然后继续完善了下,发现居然通过了pta的测评(开心.jpg),我还把注释写得更清楚了些,希望能方便你们看懂,有什么疑惑或者能给予我帮助的小伙伴可以留言噢......

#include<iostream>
using namespace std;

int main()
{
    int sum,n=0,half;  //n为第一层的空格数,设为0 
    int num,x,f=1;  //num是输入点的个数 
    char ch;
    cin>>num>>ch;
    sum=num;
    half=(num-1)/2;   //half是除去中间一层外,剩余点数的一半 
    for(x=3;half>=x;x+=2) {   
        half-=x;   
    }  
    x-=2;  //x记录下最多个数的一层(最顶层)的个数,由于多循环了一次,故x-=2才是有效个数 
    for(int j=x;;j-=2){
        if(j==1) {   //当个数只够拼出一个点时,剩余点数=总点数-1 
            sum--;
            break;
        }
        else{
            sum=sum-j*2;  //当个数可以拼出不止一个点时,剩余点数=总点数-每层个数*2(因为有对称的上下两层) 
            f++;  //f记录有效层数(中间一层外的其他层数/2) 
        }
    }
    int F=f;
    int sign=x;
    while(f>=1){   //当它有多层时 
        for(x=0;x<n;x++){
            cout<<" ";  //输出该有的空格数 
        }
        for(x=0;x<sign;x++) {
            cout<<ch;
        }
        n++;   //打印下一行时空格数量比上一层多1,故n++ 
        f--;   //需要打印的层数减少一层 
        sign-=2;   //新的一层的点数较上一层少2 
        cout<<endl;
    }
    f=2;   //f表示从第二层(中间一层的下一层)开始,f从2开始是因为上面的while循环已经输出了最中间的一个点
    n-=2;   //由于上面while循环最后一次时n多加了1 ,并且在打印中间一层后继续打下一层时该层的空格是较中间一层少1,故n要减少两个 
    sign+=4;
    while(f<=F){   //从f层打印到F层 
        for(x=0;x<n;x++){
            cout<<" ";
        }
        for(x=0;x<sign;x++) {
            cout<<ch;
        }
        n--;   //下半层每层个空格数比上一层少1 
        f++;   //准备打印下一层 
        sign+=2;  //下一层的点数较上一层多2 
        cout<<"\n";
    }
    cout<<sum<<endl;
    return 0;
}

可能看感觉似懂非懂,我大概说一下为什么要使f=2: 

就上图而言:记录f的for循环里,得到的f的值是第一、二、三层的层总数(f的初始值为1,两次+1后为3),即f=3(橙色框),故后文的F=f=3,第二个while使f=2是使之从第二层开始打印(绿色框),从第二层开始打印到第三层。依次推论,要是有更多层和更多点时,只是F变化,(假设橙色框层数=6,打印下半层时依然从第f=2层开始,打印到第F=6层时结束)

(欢迎并感谢各位的解惑和指正 >-< )

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
根据提供的引用内容,这段代码是用来统计输入数字中奇数和偶数的个数的。代码中使用循环遍历输入的数字,通过对2取模运算来判断数字是奇数还是偶数,然后分别对奇数和偶数的计数变量进行加一操作。循环结束后,输出奇数计数变量和偶数计数变量的值,中间用空格隔开。\[1\]\[2\]\[3\] 这段代码可以用来解决团体程序设计天梯赛-练习集 L1-022 奇偶分家的问题。 #### 引用[.reference_title] - *1* [PTA团队天梯赛║L1-022 奇偶分家](https://blog.csdn.net/m0_46492118/article/details/114481127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [PAT团队程序设计天梯赛-习题集L1-022 奇偶分家](https://blog.csdn.net/qq_38234015/article/details/81291913)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [团体程序设计天梯赛-练习集 L1-022 奇偶分家 (10分)(C语言)](https://blog.csdn.net/Baridhu/article/details/109899606)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值