1.迷宫求解
2.八皇后
非递归
#include <stdio.h>
#include <math.h>
#include <malloc.h>
void nQueens(int *x, int n); /*求解n皇后问题*/
int place(int *x, int k); /*判断是否可以在第k行第x[k]列摆放皇后*/
void printSolution(int *x, int n); /*输出求解结果*/
int main()
{
int n;
int *x; /*存放求解结果的数组首地址*/
scanf("%d", &n);
x=(int*)malloc(sizeof(int)*(n+1)); /*动态分配数组空间, x[0]空闲*/
nQueens(x, n);
return 0;
}
/*如果一个皇后能放在第k行第x[k]列,则返回真(1),否则返回假(0)*/
int place(int *x, int k)
{
int i;
/*对前k-1行,逐行考察*/
for(i=1; i<k; i++)
{
/*如果前k-1行中有某行的皇后与第k行的在同一列或同一斜线,返回0*/
if((x[i]==x[k])||(fabs(x[i]-x[k])==fabs(i-k)))
return 0;
}
/*能执行下一句,说明在第k行第x[k]列摆放皇后,不会互相攻击*/
return 1;
}
/*求解在n×n的棋盘上,放置n个皇后,使其不能互相攻击*/
void nQueens(int *x, int n)
{
int k;
k = 1; /*k是当前行*/
x[k] = 0; /*x[k]是当前列,进到循环中,立刻就会执行x[k]++,而选择了第1列*/
while(k>0)/*当将所有可能的解尝试完后,k将变为0,结束求解过程*/
{
x[k]++; /*移到下一列*/
while(x[k]<=n && !place(x, k)) /*逐列考察,找出能摆放皇后的列x[k]*/
x[k]++;
if(x[k]<=n) /*找到一个位置可以摆放皇后*/
{
if(k==n) /*是一个完整的解,输出解*/
printSolution(x, n);
else /*没有完成最后一行的选择,是部分解,转向下一行*/
{
k++; /*接着考察下一行*/
x[k]=0; /*到循环开始执行x[k]++后,下一行将从第1列开始考察*/
}
}
else /*对应x[k]>n的情形,这一行已经没有再试的必要,回溯到上一行*/
k--; /*上一行在原第x[k]列的下1列开始考察*/
}
}
/*输出求解结果*/
void printSolution(int *x, int n)
{
int i, j;
for (i = 1; i <= n; i++) /*输出第i行*/
{
for (j=1; j<=n; j++)
{
if (j == x[i]) /*第x[i]列输出Q,其他列输出*号 */
printf("Q");
else
printf("*");
}
printf("\n");
}
printf("\n");
}
3.矩形对角点最短路径
问题描述,每次只能向上下左右四个方向移动一步,求从点(x,y)到(m,n)最短步数的走法。
分析:从题意可知要使步数最少,则必须是往右或者往上走,且最大步数肯定为(m-x)+ (n-y);如此则有两种解法,递归的树深度搜索,非递归的栈式回溯。下面列出代码。
方法一:递归求解。
int num = 0;
void Search(int x, int y, int m, int n){
if(x==m||y==n){//不走回头路,所以只要或就行
num++;
return;
}
search(x+1,y,m,n);//右走
search(x,y+1,m,n);//上周
}
方法二:栈式回溯
int search(int x, int y, int m, int n){//回溯法
//if(m == n == 1)
// return 1;
int f[m+n-1] = {0};
int sum = 0;
int k = 1;
while(k>0){
if(x == m -1){
sum++;
k--;
x--;
continue;
}
else if(y == n - 1){
sum++;
k--;
y--;
continue;
}
if(f[k] == 0){
f[k]++;
k++;
x++;
}
else if(f[k] == 1){
f[k]++;
k++;
y++;
//continue;
}
else if(f[k] == 2){
f[k] = 0;//清0,方便再次进入
if(f[k-1] == 2)//判断回溯方向
y--;
else
x--;
k--;
}
}
return sum;
}
动态规划法:由递归式可知状态转移方程为s[i][j] = s[i-1][j] + s[i][j],i,j>0.代码如下:
int s[101][101] = {0};
int uniquePaths(int m, int n) {//递归法
//return search(0, 0, m, n);
//vector<int> temp(n,0);
// vector<vector<int>> vt_rt(m,temp);
int max = m>n?m:n;
for(int i = 1; i <= max; i++)//初始化
{
s[1][i] = 1;
s[i][1] = 1;
}
for(int i = 2; i <= m; i++)
for(int j = 2; j <= n; j++)
s[i][j] = s[i-1][j] + s[i][j-1];
return s[m][n];
}