PAT B1027 打印沙漏

Posted mrdragon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PAT B1027 打印沙漏相关的知识,希望对你有一定的参考价值。

PAT B1027 打印沙漏

题目描述:

  本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
  *****
   ***
    *
   ***
  *****
  所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差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 打印沙漏的主要内容,如果未能解决你的问题,请参考以下文章

B1027打印沙漏

PAT 1027. 打印沙漏

1027. 打印沙漏(PAT)

PAT——1027. 打印沙漏

PAT-乙级-1027 打印沙漏

PAT 1027. 打印沙漏(20)