算法分析与设计实验三 回溯法 24点问题 n皇后问题

实验目的
学习编程实现深度优先搜索状态空间树求解实际问题的方法, 着重体会求解第一个可行解和求解所有可行解之间的差别。 加深理解回溯法通过搜索状态空间树、同时用约束函数剪去不含答案状态子树的算法思想, 会用蒙特卡罗方法估计算法实际生成的状态空间树的结点
数。

实验内容
1、 求 24 点问题
给定四个 1-9 之间的自然数, 其中每个数字只能使用一次,用算术运算符+,-,*,/构造出一个表达式,将这 4 个正整数连接起来(可以使用括号),使最终的得数为 24。 要求根据问题的特征设计具体算法并编程实现, 输入数据为 4 个自然数。输出若有多个满足要求的表达式, 则只输出其中一组; 若搜索失败, 则输出“ Fail!”。
【示例】 采用一个表达式中用括号确定运算先后次序的方式,如:
输入 1, 5, 5, 5 四个自然数,输出((5-(1/5))*5)。
输入 3, 3, 8, 8 四个自然数,输出(8/(3-(8/3)))。
【测试数据】
(1) 1,5,5,5 (2) 3,3,8,8 (3) 3,8,8,8 (4) 1,2,3,4 (5) 2,4,5,6
(6) 4,2,2,5 (7) 1,2,2,6 (8) 4,2,8,8 (9) 0,3,8,8
2、 n 皇后问题
要求用回溯法求解 8-皇后问题, 使放置在 8*8 棋盘上的 8 个皇后彼此不受攻击, 即:任何两个皇后都不在同一行、 同一列或同一斜线上。 请输出 8 皇后问题的所有可行解。

24点程序:

/*   Function : 求解24点问题,回溯,dfs。
 *   Name     : 24点.cpp
 *   Author   : wyh7280
 *   Time     : 2015.05.20 17:15:00.000
 *   Update   : 2015.05.25 12:10:00.000
 */
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
//宏定义
const double PRECISION = 1E-6; //精度常量
const int COUNT_OF_NUMBER = 4; //算24点的自然数个数
const int NUMBER_TO_BE_CAL = 24;

bool flag=false;
int cnt=0; //标记解的数量,为1时退出

class RationalNumber  //定义有理数类(分子、分母)
{
protected:
   int numerator,denominator; //numerator:分子,denominator:分母
   bool inf;
protected:
   int gcd(int a,int b) //求最大公约数,辗转相除法
   {
      int temp;
      if(anumerator=numerator;
      this->denominator=denominator;
      Simplify();
   }
   virtual ~RationalNumber() {}
   void Simplify()
   {
      if(denominator==1)
      {
         inf=false;
      }
      else if(numerator==0)
      {
         denominator=1;
         inf=false;
      }
      else
      {
         int k=gcd(abs(numerator),abs(denominator));
         numerator/=k;
         denominator/=k;
         if(denominator==1)
            inf=false;
         else
            inf=true;
      }
    }
    //重载运算符
    RationalNumber operator+(const RationalNumber& b) const
    {
        RationalNumber result;
        result.denominator=this->denominator*b.denominator;
        result.numerator=this->numerator*b.denominator+this->denominator*b.numerator;
        result.Simplify();
        return result;
    }
    RationalNumber operator-(const RationalNumber& b) const
    {
        RationalNumber result;
        result.denominator=this->denominator*b.denominator;
        result.numerator=this->numerator*b.denominator-this->denominator*b.numerator;
        result.Simplify();
        return result;
    }
    RationalNumber operator*(const RationalNumber& b) const
    {
        RationalNumber result;
        result.denominator=this->denominator*b.denominator;
        result.numerator=this->numerator*b.numerator;
        result.Simplify();
        return result;
    }
    RationalNumber operator/(const RationalNumber& b) const
    {
        RationalNumber result;
        result.denominator=this->denominator*b.numerator;
        result.numerator=this->numerator*b.denominator;
        result.Simplify();
        return result;
    }
    RationalNumber& operator=(const RationalNumber& b)
    {
        denominator=b.denominator;
        numerator=b.numerator;
        return (*this);
    }
    RationalNumber& operator=(int b)
    {
        denominator=1;
        numerator=b;
        return (*this);
    }
    int Numerator() const
    {
        return numerator;
    }
    int Denominator() const
    {
        return denominator;
    }
    string strshow()
    {
        string str;
        char buffer[20];
        itoa(numerator,buffer,10);
        str=buffer;
        if(denominator!=1)
        {
            itoa(denominator,buffer,10);
            str=str+"/"+buffer;
        }
        return str;
    }
};

RationalNumber number[COUNT_OF_NUMBER];  //用数组number[]保存操作数
string expression[COUNT_OF_NUMBER];      //用数组expression[]保存算式

bool Search(int n) //递归函数负责寻找可行解,其中 n 为本层调用的操作数个数。 每次两
                   //数运算后,原来的两个操作数被去除,运算结果成为新的操作数,因此总的操作数数量减 1。
{
    if (n==1)
    {
       if (fabs(number[0].Numerator ()*1.0/number[0].Denominator ()-NUMBER_TO_BE_CAL)=0)
   {
  //  Search(n-1);
      if(Search(n-1)&&n!=4)
      {
         number[i]=a;
         number[j]=b;
         expression[i]=expa;
         expression[j]=expb;
         return true;
      }
   }

   expression[i]='('+expb+'-'+expa+')';
   number[i]=b-a;
   if(number[i].Numerator() >=0)
   {
       //  Search(n-1);
      if(Search(n-1)&&n!=4)
      {
         number[i]=a;
         number[j]=b;
         expression[i]=expa;
         expression[j]=expb;
         return true;
      }
   }
   //乘法
   expression[i]='('+expa+'*'+expb+')';
   number[i]=a*b;
  // Search(n-1);
   if(Search(n-1)&&n!=4)
   {
       number[i]=a;
       number[j]=b;
       expression[i]=expa;
       expression[j]=expb;
       return true;
    }
   //除法也有两种情况a/b和b/a
   if(b.Numerator()!=0)
   {
       expression[i]='('+expa+'/'+expb+')';
       number[i]=a/b;
    // Search(n-1);
      if(Search(n-1)&&n!=4)
      {
        number[i]=a;
        number[j]=b;
        expression[i]=expa;
        expression[j]=expb;
        return true;
      }
   }
   if(a.Numerator()!=0)
   {
      expression[i]='('+expb+'/'+expa+')';
      number[i]=b/a;
     // Search(n-1);
     if(Search(n-1)&&n!=4)
     {
       number[i]=a;
       number[j]=b;
       expression[i]=expa;
       expression[j]=expb;
       return true;
     }
   }
   //本轮调用完毕后,用a,b,expa,expb将数组number[]和expression[]恢复原状
    number[i]=a;
    number[j]=b;
    expression[i]=expa;
    expression[j]=expb;
   }
  }
  return false;
}

int main()
{
    int x;
    cout<<"Please input four integers:";
    flag=false;
    for(int i=0;i>x;
        number[i]=x;
        itoa(x,buffer,10); //itoa():将一个10进制的integer数转换为string类型
        //即:把输入的int型操作数x,转变成可以放在buffer[]中的string类型
        expression[i]=buffer; //用expression[i]指针指向buffer[]数组空间的起始位置
    }
    Search(4);
    if(flag==false)
    cout<<"Fail\n";
 return 0;
}

n皇后程序(主函数调用实现8皇后求解)

/*   Function : 求解 n-皇后问题,本题求解8皇后(可自行修改n值),用回溯法深度优先遍历状态空间树, 并利用约束函数进行剪枝。
 *   Name     : 8皇后问题.cpp
 *   Author   : wyh7280
 *   Time     : 2015.05.26 12:01:00.000
 *   Update   : no
 */
#include 
#include 
#include 
#include 
using namespace std;

bool Place(int k,int i,int *x);
void NQueens(int k,int n,int *x);;
void NQueens(int n,int *x);

int main()
{
    int x[8];
    for(int i=0;i<8;i++) x[i]=-1;
    NQueens(8,x);
}

bool Place(int k,int i,int *x) //判定两个皇后是否在同一列或在同一斜线上
{
   for (int j=0;j


你可能感兴趣的:(算法分析与设计实验三 回溯法 24点问题 n皇后问题)