简单记录下这道题目貌似只通过了一个测试点。然后今天再修改了下,第二个测试点没过,后来知道是因为没分情况(输入个数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层时结束)
(欢迎并感谢各位的解惑和指正 >-< )