一直以来,觉得软考最实用的部分,就是算法及java或c++程序设计部分了,也是自己需要长期掌握的,从今天开始正式复习此部分。
做题时一定要结合上下文进行作答,要相信,正确答案一定是最简单的。
主要是自己还没写过的算法及概念的复习还有就是java或c++的语法。
如2019年上半年下午题第4题。
第4题:阅读下列说明和C代码,回答问题1至问题3,将解答写在答题纸的对应栏内。
【说明】
n皇后问题描述为:在一个n×n的棋盘上摆放n个皇后,要求任意两个皇后不能冲突,即任意
两个皇后不在同一行、同一列或者同一斜线上。
算法的基本思想如下:
将第i个皇后摆放在第i行,i从1开始,每个皇后都从第1列开始尝试。尝试时判断在该列摆放
皇后是否与前面的皇后有冲突,如果没有冲突,则在该列摆放皇后,并考虑摆放下一个皇
后;如果有冲突,则考虑下一列。如果该行没有合适的位置,回溯到上一个皇后,考虑在原
来位置的下一个位置上继续尝试摆放皇后,......,直到找到所有合理摆放方案。
【C代码】
下面是算法的C语言实现。
(1)常量和变量说明
n: 皇后数,棋盘规模为n×n
queen[]: 皇后的摆放位置数组, queen[i]表示第i个皇后的位置, 1≤queen[i]≤n
(2)C程序
#include
#define n 4
int queen[n+1];
void Show(){ /* 输出所有皇后摆放方案 */
int i;
printf("(");
for(i=1;i<=n;i++){
printf(" %d",queen[i]);
}
printf(") ");
}
int Place(int j){ /* 检查当前列能否放置皇后,不能放返回0,能放返回1 */
int i;
for(i=1;i
return 0;
}
}
return (2) ;
}
void Nqueen(int j){
int i;
for(i=1;i<=n;i++){
queen[j] = i;
if( (3) ){
if(j == n) { /* 如果所有皇后都摆放好,则输出当前摆放方案 */
Show();
} else { /* 否则继续摆放下一个皇后 */
(4) ;
}
}
}
}
int main(){
Nqueen (1);
return 0;
}
问题:4.1【问题1】(8分)
根据题干说明,填充C代码中的空(1)〜(4)。问题:4.2【问题2】(3分)
根据题干说明和C代码,算法采用的设计策略为 (5)。问题:4.3【问题3】(4分)
当n=4时,有 (6) 种摆放方式,分别为 (7)
答:像这种算法填空的题,难度还是不小的,如何作答?
明白算法的思想后,就是看代码实现了,一定要搞明白每个变量及数组,也就是先明白抽象出来的数据结构,这点与我们平时写算法时的思路是一样的。并结合算法思想,如何用给的这些变量来实现算法?
这题是第一次见代码,所以一头雾水。
第一空,可以根据提示,不能放返回0,能放返回1 ,if()里放的是return 0,不能放的情况,该填什么呢?可以看到后面是斜线的情况,那么就应该填在同一行上的情况 。应该填 queen[i]==queen[j];
第二空 ,很简单,能放的话是 返回1
第三空:不好填,先看第四空,提示是继续摆放下一个皇后,所以应该填本函数的递归调用Nqueen(j+1)
若之前没接触过N皇后问题,估计很难答对,正确的是Place(j)&&j
n皇后问题:
约束条件:除了不能在同一行,同一列外,还不能在同一斜线
其实并不需要一个n*n的数组,我们只需要一个n长度的数组来存位置。
表示方式: arr[i] = k; 表示: 第i行的第k个位置放一个皇后。这样一个arr[n]的数组就可以表示一个可行解, 由于回溯,我们就可以求所有解。
/**
* n皇后问题解决
* @author lin
*
*/
#include
#include
#include
using namespace std;
/**皇后的数目*/
static int num;
/**下标i表示第几行,x[i]表示第i行皇后的位置,注意此处0行不用*/
static int *x;
/**解的数目*/
static int sum = 0;
/**
* 判断第k行皇后可以放置的位置
* @param k k表示第k行,X[K]k表示第k行上皇后的位置
* @return boolean false表示此处不能放置皇后
*/
bool place( int k )
{
for ( int j = 1; j < k; j++ )
{
/* 如果当前传入的第K行上的皇后放置的位置和其它皇后一个对角线(abs(x[k]- x[j])==abs(k-j)或一个直线上(x[j] == x[k]) */
if ( abs( x[k] - x[j] ) == abs( k - j ) || x[j] == x[k] )
{
return(false);
}
}
return(true);
}
/**
* 一行一行的确定该行的皇后位置
* @param t
*/
void backtrack( int t )
{
if ( t > num ) /* 如果当前行大于皇后数目,表示找到解了 */
{
sum++;
/* 依次打印本次解皇后的位置 */
for ( int m = 1; m <= num; m++ )
{
//cout << x[m]; /* 这一行用输出当递归到叶节点的时候,一个可行解 */
//这里只是为了好看才写成下面的
for(int k =1; k <= num;k++){
if(k == x[m]){
cout << x[m] << ;
}else {
cout << * ;//用*表示没有被用到的位置
}
}
cout << endl;
}
cout << endl;
} else {
for ( int i = 1; i <= num; i++ )
{
x[t] = i; /* 第t行上皇放在i列处 */
if ( place( t ) )
{
/* 此处的place函数用来进行我们上面所说的条件的判断,如果成立,进入下一级递归 */
backtrack( t + 1 );
}
}
}
}
int main()
{
cout<<请输入皇后数目:;
cin>>num;
clock_t start,finish;
double totaltime;//计算程序运行时间
start=clock();//起始时间
x = new int[num + 1]; /* 此处注意加1,这里0行不用,1-num分别对应1-num行 */
for ( int i = 0; i <= num; i++ )
x[i] = 0;
backtrack( 1 ); /*传入第一个皇后,开始递归 */
cout << 方案共有 << sum;
delete[]x;
finish=clock();//结束时间
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
cout<<此程序的运行时间为<