赞
踩
简单记录下这道题目貌似只通过了一个测试点。然后今天再修改了下,第二个测试点没过,后来知道是因为没分情况(输入个数n>=7或n<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层时结束)
(欢迎并感谢各位的解惑和指正 >-< )
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。