习题(15-1) 前缀表达式 (1010)
描述 | |
前缀表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的前缀表示法为+ 2 3。前缀表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的前缀表示法为* + 2 3 4。本题求解前缀表达式的值,其中运算符包括+ - * /四个。 | |
关于输入 | |
输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数。 | |
关于输出 | |
输出为一行,表达式的值。 可直接用printf("%f\n", v)输出表达式的值v。 | |
例子输入 | |
* + 11.0 12.0 + 24.0 35.0 | |
例子输出 | |
1357.000000
| |
提示 | |
可使用atof(str)把字符串转换为一个double类型的浮点数。atof定义在stdlib.h中。 此题可使用函数递归调用的方法求解。 |
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream>
2 #include<cstring>
3 using namespace std;
4 char str[100][20]; //定义一个字符数组,以空格为界,每行存放一个符号或数
5 int strcount = 0; //定义符号和数的总数目
6 double res; //定义结果
7 void input() //此函数用作输入表达式,存入数组
8 {
9 int i = 1, j = 0;
10 char ch;
11 while (cin.get(ch))
12 {
13 if (ch == ' ')
14 {
15 i++;
16 j = 0;
17 }
18 else if (ch == '\n')
19 break;
20 else
21 {
22 str[i][j] = ch;
23 j++;
24 }
25 }
26 strcount = i;
27 }
28 int calc(int num) //此函数用以递归计算
29 {
30 double sum,a1,a2;
31 if (num == 0)
32 {
33 res = atof(str[1]);
34 return 0;
35 }
36 if (str[num][0] == '+')
37 {
38 a1 = atof(str[num + 1]); a2 = atof(str[num + 2]);
39 sum = a1 + a2;
40 sprintf(str[num], "%.10f", sum);
41 for (int i = 3; i <= strcount - num; i++)
42 strcpy(str[num + i - 2], str[num + i]);
43 }
44 else if (str[num][0]=='*')
45 {
46 a1 = atof(str[num + 1]); a2 = atof(str[num + 2]);
47 sum = a1 * a2;
48 sprintf(str[num], "%.10f", sum);
49 for (int i = 3; i <= strcount - num; i++)
50 strcpy(str[num + i - 2], str[num + i]);
51 }
52 else if (str[num][0] == '/')
53 {
54 a1 = atof(str[num + 1]); a2 = atof(str[num + 2]);
55 sum = a1/ a2;
56 sprintf(str[num], "%.10f", sum);
57 for (int i = 3; i <= strcount - num; i++)
58 strcpy(str[num + i - 2], str[num + i]);
59 }
60 else if (str[num][0] == '-')
61 {
62 a1 = atof(str[num + 1]); a2 = atof(str[num + 2]);
63 sum = a1 - a2;
64 sprintf(str[num], "%.10f", sum);
65 for (int i = 3; i <= strcount - num; i++)
66 strcpy(str[num + i - 2], str[num + i]);
67 }
68 calc(num - 1);
69 }
70 int main()
71 {
72 input();
73 calc(strcount);
74 printf("%f\n", res);
75 }
猴子分苹果
描述 | |
有1堆苹果共 m 个,由 n 只猴子按个数平均分配。每次到达苹果堆放地的猴子只有1只,而且每个猴子都会平均分 1 次苹果。第1个到达的猴子将苹果平均分成 n 等份,但发现多 k ( k < n )个,于是,将多余的k个扔掉,然后拿走其中的1等份。第 2 个猴子同样将剩余的苹果又分成 n 等份,也发现多 k 个,并同样将多余的 k 个扔掉,然后拿走其中1等份。之后的每个猴子都这样(将剩余的苹果又分成 n 等份,也发现多 k 个,并将多余的 k 个扔掉,然后拿走其中1等份)。假设最后的猴子分配后至少可以拿走1个苹果,请根据输入的 n 和 k值,计算最小的 m | |
关于输入 | |
输入猴子数目n 和扔掉的个数 k,其中 k 小于 n,n 和 k 之间以空格间隔。 | |
关于输出 | |
输出最小苹果数目 | |
例子输入 | |
2 1 | |
例子输出 | |
7 |
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream>
2 using namespace std;
3 int n, k,i=1; //定义初始值
4 int monk(int p, int k) //此函数用以递归求值
5 {
6 int num;
7 if (p == 1) //当猴子只剩一只的时候,最小值为n*i+k
8 return n*i + k;
9 else
10 {
11 num = monk(p - 1, k) / (n - 1)*n + k;
12 if (monk(p - 1, k) % (n - 1) == 0) //当这种i取值符合时,正常输出
13 return num;
14 else //不符合时,换一个i,继续尝试
15 {
16 i++;
17 return monk(p, k);
18 }
19 }
20 }
21 int main()
22 {
23 cin >> n>>k;
24 cout << monk(n, k);
25 return 0;
26 }
二叉树
描述 | |
| |
关于输入 | |
输入只有一行,包括两个正整数x和y,这两个正整数都不大于1000。 | |
关于输出 | |
输出只有一个正整数xi。 | |
例子输入 | |
10 4 | |
例子输出 | |
2 |
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream>
2 #include<cmath>
3 using namespace std;
4 int search(int row,int x) //此函数用以找出x到1路径的下一步将是哪个数,并直接赋给x
5 {
6 double mul=row;
7 return pow(2, mul - 1) + (x - pow(2,mul)) / 2;
8 }
9 int check(int x, int y) //此函数用于判断此时x和y是否相等
10 {
11 int sizex, sizey;
12 for (int i = 1;; i++) //下面两个循环分别求出x,y处于第几行
13 {
14 double mul = i;
15 if (x <= pow(2, mul)-1)
16 {
17 sizex = i - 1;
18 break;
19 }
20 }
21 for (int i = 1;; i++)
22 {
23 double mul = i;
24 if (y <= pow(2,mul)-1)
25 {
26 sizey = i - 1;
27 break;
28 }
29 }
30 if (y > x) //如果y比x大,对y进行search,然后递归
31 {
32 y = search(sizey, y);
33 check(x, y);
34 }
35 else if (y == x)
36 return x;
37 else if(x>y)
38 {
39 x = search(sizex, x);
40 check(x, y);
41 }
42 }
43 int main()
44 {
45 int x, y;
46 cin >> x >> y;
47 cout << check(x, y) << endl;
48 return 0;
49 }
红与黑
描述 | |
有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的四块瓷砖中的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。 | |
关于输入 | |
包括多个数据集合。每个数据集合的第一行是两个整数W和H,分别表示x方向和y方向瓷砖的数量。W和H都不超过20。在接下来的H行中,每行包括W个字符。每个字符表示一块瓷砖的颜色,规则如下 ‘.’:黑色的瓷砖 ‘#’:红色的瓷砖 ‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中仅出现一次 当在一行中读入的是两个零时,表示输入结束。 | |
关于输出 | |
对每个数据集合,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。 | |
例子输入 | |
6 9
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
11 9
.#.........
.#.#######.
.#.#.....#.
.#.#.###.#.
.#.#..@#.#.
.#.#####.#.
.#.......#.
.#########.
...........
11 6
..#..#..#..
..#..#..#..
..#..#..###
..#..#..#@.
..#..#..#..
..#..#..#..
7 7
..#.#..
..#.#..
###.###
...@...
###.###
..#.#..
..#.#..
0 0 | |
例子输出 | |
45
59
6
13 |
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream>
2 #include<cmath>
3 using namespace std;
4 int col,row,bcount=0; //定义行列数,计数
5 char ch[21][21]; //定义石砖分布
6 void hh(int x, int y) //此函数用于弄清有几块可以走到的石砖
7 {
8 if (x<1 || x>row || y<1 || y>col || ch[x][y] != '.')
9 return;
10 else
11 {
12 ch[x][y] = '#'; //一块黑砖走到以后就把他变成红的防止重复走
13 bcount++;
14 hh(x+1,y); hh(x-1,y);
15 hh(x, y + 1); hh(x, y - 1);
16 }
17 }
18 int main()
19 {
20 int startcol, startrow;
21 while (1)
22 {
23 cin >>col >> row; //进行输入
24 if (col == 0)
25 return 0;
26 for (int i = 1; i <= row; i++)
27 for (int j = 1; j <= col; j++)
28 {
29 cin >> ch[i][j];
30 if (ch[i][j] == '@') //遇到@时把他变成.,记下方位
31 {
32 startcol = j; startrow = i;
33 ch[i][j] = '.';
34 }
35 }
36 hh(startrow, startcol);
37 cout << bcount << endl;
38 bcount = 0;
39 }
40
41 return 0;
42 }
放苹果问题
描述 | |
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法(用K表示)?注意:5,1,1和1,5,1是同一种分发。 | |
关于输入 | |
第一行是测试数据的数目t(0<= t <= 20),其后的t行均包含两个整数M和N,以空格分开。 1<= M <= 25; 1<= N <= 10; | |
关于输出 | |
对输入的每组数据M和N,用一行输出相应的K | |
例子输入 | |
1
7 3 | |
例子输出 | |
8 | |
提示 | |
采用递归思想解题。 |
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream>
2 #include<cmath>
3 using namespace std;
4 int app(int m, int n) //此函数用以递归求出方案数
5 {
6 if (m == 0 || n == 1) //最终情况是m=0或者n=1时候的,此时有一种方案符合
7 return 1;
8 else
9 {
10 if (m >= n) //当盘子不比苹果多,有放满和不放满两种情况
11 return app(m, n - 1) + app(m - n, n);
12 else //当盘子比苹果多,必须有n-m个盘子是空的,相当于m个苹果放在m个盘子
13 return app(m, m);
14 }
15 }
16 int main()
17 {
18 int co;
19 cin >> co;
20 for (int i = 1; i <= co; i++)
21 {
22 int m, n;
23 cin >> m >> n;
24 cout << app(m, n) << endl;
25 }
26 return 0;
27 }
1090 分解因数
描述 | |
给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * ... * an,并且1 < a1 <= a2 <= a3 <= ... <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。 | |
关于输入 | |
第1行是测试数据的组数n,后面跟着n行输入。每组测试数据占1行,包括一个正整数a (1 < a < 32768) | |
关于输出 | |
n行,每行输出对应一个输入。输出应是一个正整数,指明满足要求的分解的种数 | |
例子输入 | |
2
2
20 | |
例子输出 | |
1
4 |
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream>
2 #include<cmath>
3 using namespace std;
4 int sum = 1; //定义一个全局变量,是输出结果
5 void res(int m,int a) //此函数用于算出,当最小的因数大于等于a时,m的分法有几种
6 {
7 for (int i =a; i <= sqrt(m); i++) //循环出不同情况,并且因为因数从小到大,i有最大界限
8 {
9 if (m%i == 0) //当i是因数的时候,多一种分法,并递归余数
10 {
11 sum++;
12 res(m / i,i);
13 }
14 }
15 }
16 int main()
17 {
18 int n,a;
19 cin >> n;
20 for(int i=1;i<=n;i++)
21 {
22 cin >> a;
23 res(a,2); //初始时,最小因数大于等于2
24 cout << sum << endl;
25 sum = 1;
26 }
27 }