慕课第二章 递归(一)例题3: N皇后 ,例题4:逆波兰表达式求值

题目

皇后问题:输入整数N,要求N个国际象棋的皇后,摆在N*N的棋盘上,互相不能攻击,输出全部方案。

思路 

 输入一个正整数N,则程序输出N皇后问题的全部摆法。输出结果里的每一行2都代表一种摆法。行里的第i个数字如果是n,就代表第i行的皇后应该放在第n列。皇后的行、列编号都是从1开始运算。

代码编写

(1)main()函数

首先在所有函数外设置一个一个全局变量N,在定义一个用来存放皇后位置的数组,然后从最简单的主函数main说起,先输入几个皇后,从而确定好一个大概的表格框架,再调用nqueen()函数(注意:从第0行开始摆皇后,以确保每个位置都被尝试一遍)。

int N;
int queenpos[100];用来存放算好的皇后位置,最左上角是(0,0)

int main()
{
  cin>>N;
  nqueen(0);首先从第0行开始摆皇后
  return 0;
}

(2)nqueen()函数

定义的nqueen函数是最该程序中最重要的一部分,首先是看定义的一个参数k是否与输入的皇后N相同,若相等,则说明N个皇后已经排好序了,则输出N个皇后的具体位置queenpos[i]+1(由于是从坐标(0,0)开始,所以输出的位置都要加1)," "负号内有一个空格,表示输出的结果之间有1个间距。

进入列循环,从i=0开始,进行执行,由于k开始也等于0,程序跳到if(k==j),从而确定好第一个皇后的位置(0,0)。再依次执行i=1,进行判断该皇后是否与前一个位置在同一行或者是在对角线上,显然在第二列的位置不能放皇后,然后再执行i=2,i=3可以放置皇后,但在当i=1时不能放置,说明该步骤是错误的,于是程序将重新开始从(1,0)开始放置,周而复始,便考虑到了所以的方案。

void nqueen(int k)
{
	int i, j;
	if (k == N)
	{
		for (i = 0; i < N; i++)
			cout << queenpos[i] + 1 << " ";  //输出排列好后N个皇后的位置
			cout << endl;
			return;
	}
	for (i = 0; i < N; i++) //进行列循环
	{
		for (j = 0; j < k; j++) //进行行循环
		{
			if (queenpos[j] == i || abs(queenpos[j]-i) == k - j)  //判断后一个皇后是否与前一个皇后在同一列,或者是在对角线上
			{
				break;
			}
		}
		if (k == j)
		{
			queenpos[k] = i;
			nqueen(k + 1);
		}
	}
}

完整代码如下:

#include<iostream>
#include<cmath>
using namespace std;
int N;  //定义N个皇后    
int queenpos[100]; //存放皇后的位置
void nqueen(int k);
int main()
{
	cin >> N;
	nqueen(0);  //从第0行开始摆皇后
	return 0;
}
void nqueen(int k)
{
	int i, j;
	if (k == N)  //N个皇后已经摆好
	{
		for (i = 0; i < N; i++)  
			cout << queenpos[i] + 1 << " "; //输出皇后的位置
			cout << endl;
			return;
	}
	for (i = 0; i < N; i++)  //列循环    
	{
		for (j = 0; j < k; j++)  //行循环
		{
			if (queenpos[j] == i || abs(queenpos[j]-i) == k - j) //判断是否和摆好的皇后冲突
			{
				break;
			}
		}
		if (k == j) //当前选的位置i不冲突
		{
			queenpos[k] = i; //将第k个皇后摆在位置i
			nqueen(k + 1);  //进行递归,摆下一个皇后
		}
	}
}

题目

逆波兰表达式:逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2+3的逆波兰表示法为+ 2 3。逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2+3) * 4的逆波兰表示法为* + 2 3 4。本题求解逆波兰表达式的值,其中运算符包括+ - * /四个

 样例输入

* + 11.0 12.0 +24.0 35.0

样例输出

1357.000000

提示(11.0+12.0)*(24.0+35.0)

思路

首先了解逆波兰表达式定义:(1)1个数就是一个逆波兰表达式,值为该数。

                                               (2)“运算符+空格+逆波兰表达式+空格+逆波兰表达式”是逆波兰表达式,值为俩逆波兰表达式运算结果。

采用递归的形式,先定义一个exp函数来读入并算出逆波兰表达式的值,让后读入数据s,利用switch语句进行运算,若首个读入的是运算符,则再调用exp()函数读入两个波兰表达式;若首次读入的是一个数,则输出该数。

提醒:atof()函数是字符串处理函数,功能是把字符串转换成浮点数。

完整代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
double exp()  //读入并算出逆波兰表达式的值
{
	char s[20];
	cin >> s;
	switch (s[0]) {
	case '+':return exp() + exp(); //若读入+号,则继续调用exp(),读入两个逆波兰表达式
	case '-':return exp() - exp();
	case '*':return exp() * exp();
	case '/':return exp() / exp();
	default:return atof(s);  //将字符型转换成浮点型
		break;
	}
}
int main()
{
	printf("%lf", exp());
	return 0;
}

大数据201 田永兴

猜你喜欢

转载自blog.csdn.net/zjsru_Beginner/article/details/121059719