回溯和贪心
回溯
意义:编程解决问题时,常遇到需要例遍所有可能性来求解问题的情况。此时,回溯将是不错的选择。
代码示例:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*这个程序用来测试回溯算法在解决问题中的应用*/
/*
八皇后问题:
经典的八皇后问题,即在一个8*8的棋盘上放8个皇后,
使得这8个皇后无法互相攻击( 任意2个皇后不能处于同一行,同一列或是对角线上),
输出所有可能的摆放情况。
*/
/*
将以上问题引申成在n*n的棋盘上摆放n个皇后的问题。
以下代码就使用了回溯法解决n皇后问题。
*/
int place(int*,int);//判断当前位置摆放皇后是否可行
void nQueens(int*,int);//n皇后问题算法核心
void printSolution(int*,int);//用于输出已求出的解决方案
int main()
{
int n;
int *x;//指针x作为动态数组使用
scanf("%d",&n);
//为指针x动态分配n+1个int的空间。用于代替数组模拟棋盘
x=(int*)malloc(sizeof(int)*(n+1));
nQueens(x,n);//将数组和皇后数量传入,开始求解
return 0;
}
int place(int *x,int k)//形参x为模拟棋盘的数组,k为当前放置皇后的行数
{
int i;
//循环例遍数组中每一个已经确定位置的皇后
for(i=1;i<k;i++)
{
/*
以下判断条件将在以下另外解析
*/
if(x[i]==x[k]||fabs(x[i]-x[k])==fabs(i-k))
return 0;//如果第k行的皇后和第i行的皇后冲突,返回0
}
return 1;//如果没有出现任何冲突,返回1
}
void nQueens(int *x,int n)
{
int k;//定义k作为行标
k=1;//从第一行开始摆放皇后
x[k]=0;//初始化第k行
while(k>0)
{
x[k]++;//首先在第k行第1列摆放皇后
while(x[k]<=n&&!place(x,k))//判断是否可行
x[k]++;//否,则在下一列摆放
if(x[k]<=n)//判断以上循环结束之后,列数是否超标
{
if(k==n)//判断是否摆放完最后一个皇后