PAT B1027 打印沙漏
Posted mrdragon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PAT B1027 打印沙漏相关的知识,希望对你有一定的参考价值。
PAT B1027 打印沙漏
题目描述:
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
参考代码:
参考1:
设沙漏的最大边使用的符号个数为x,则可以得出此时沙漏的符号总数sum的值。其对应关系为:(x + 1) * ((x + 1) / 2) / 2 * 2 - 1 = sum。
而且对提供的符号总数store有store >= sum。
由此可以推算出x <= sqrt(2 * (sum + 1)),从而根据store求出x,需要注意的是x必须是奇数,如果的到的是偶数需要减1。
具体实现如下:
1 /**************************************************** 2 PAT B1027 打印沙漏 3 ****************************************************/ 4 #include <iostream> 5 #include <cmath> 6 7 using namespace std; 8 9 int main() 10 char symbol; 11 int store = 0; 12 13 cin >> store >> symbol; 14 15 int maxEdgeSize = int(sqrt(2.0 * (store + 1))) - 1; //最大边的符号个数 16 maxEdgeSize = maxEdgeSize % 2 == 0 ? maxEdgeSize - 1 : maxEdgeSize; //最大边的符号个数肯定是奇数 17 18 int usedCont = 0; //使用的符号个数 19 int triLevel = (maxEdgeSize - 1) / 2; //沙漏上部三角形的层数 20 //输出沙漏上不部分的倒三角 21 for (int i = 0; i <= triLevel; ++i) 22 for (int j = 0; j < i; ++j) cout << ‘ ‘; 23 for (int j = 0; j < maxEdgeSize - 2 * i; ++j) 24 cout << symbol; 25 usedCont++; 26 27 cout << endl; 28 29 30 //输出沙漏剩余的部分 31 for (int i = 1; i <= triLevel; ++i) 32 for (int j = 0; j < triLevel - i; ++j) cout << ‘ ‘; 33 for (int j = 0; j < 1 + 2 * i; ++j) 34 cout << symbol; 35 usedCont++; 36 37 cout << endl; 38 39 40 //输出剩余符号个数 41 cout << store - usedCont; 42 43 return 0; 44
参考2:
由题目可知N <= 1000,能组成沙漏结果有限可列,可以按从小到大的顺序枚举出当N小于1000时的所有的漏斗所包含的符号个数
(具体数值可以通过下面的代码得到);
1 //获取1100以内所有能组成的沙漏包含的符号数 2 int cost = 1; 3 4 cout << cost << ", "; 5 for (int i = 1; cost < 1100; ++i) 6 cost += 2 * (2 * i + 1); 7 8 cout << cost << ", "; 9
当读入提供的符号总数store的时候可以通过二分法查找到能组成的最大沙漏需要的符号总数,其位置编号 + 1就是此时沙漏下部正三角的“层数”。
参考代码如下:
1 /**************************************************** 2 PAT B1027 打印沙漏 3 ****************************************************/ 4 #include <iostream> 5 6 using namespace std; 7 8 //1100个字符时所有可能组成的沙漏的消耗 9 const int COST[23] = 1, 7, 17, 31, 49, 71, 97, 127, 161, 199, 241, 287, 337, 391, 449, 511, 577, 647, 721, 799, 881, 967, 1057 ; 10 11 //获取最大可输出漏斗的下三角的层数 12 int myFind(int left, int right, int num) 13 int mid = 0; 14 while (left < right) 15 mid = (left + right) / 2; 16 if (right - left == 1) 17 return left; 18 19 else if (COST[mid] == num) 20 return mid; 21 22 else 23 COST[mid] > num ? right = mid : left = mid; 24 25 26 27 28 int main() 29 char symbol; 30 int store = 0; 31 32 cin >> store >> symbol; 33 34 //获取最大可输出漏斗的下三角的层数 35 int triLevel = myFind(0, 22, store); 36 37 //输出漏斗上面的部分 38 for (int i = 0; i < triLevel; ++i) 39 for (int j = 0; j < i; ++j) cout << ‘ ‘; 40 for (int j = 0; j < 2 * (triLevel - i) + 1; ++j) cout << symbol; 41 cout << endl; 42 43 44 //输出漏斗下面的三角形 45 for (int i = 0; i <= triLevel; ++i) 46 for (int j = 0; j < triLevel - i; ++j) cout << ‘ ‘; 47 for (int j = 0; j < 2 * i + 1; ++j) cout << symbol; 48 cout << endl; 49 50 51 //输出剩余符号数 52 cout << store - COST[triLevel]; 53 54 return 0; 55
注意事项:
无。
以上是关于PAT B1027 打印沙漏的主要内容,如果未能解决你的问题,请参考以下文章