一、 实验目的和要求
学习编程实现深度优先搜索状态空间树求解实际问题的方法,着重体会求解第一个可行解和求解所有可行解之间的差别。加深理解回溯法通过搜索状态空间树、同时用约束函数剪去不含答案状态子树的算法思想,会用蒙特卡罗方法估计算法实际生成的状态空间树的结点数。
二、实验环境(实验设备)
VsialStudio 2017
三、 实验原理及内容
1. 要求用回溯法求解8-皇后问题,使放置在8*8棋盘上的8个皇后彼此不受攻击,即:任何两个皇后都不在同一行、同一列或同一斜线上。请输出8皇后问题的所有可行解。
源代码:
#include<iostream>
#include<math.h>
using namespace std;
bool Place(int k, int i, int *x); //判定两个皇后是否在同一列或在同一斜线上
void NQueens(int k, int n, int *x); //递归函数(求解n皇后问题)
void NQueens(int n, int *x);
bool Place(int k, int i, int *x)
{
for (intj = 0; j < k; j++) {
if((x[j] == i) ||( abs(x[j] - i) == abs(j - k))) {
returnfalse;
}
}
returntrue;
}
void NQueens(int k, int n, int *x)
{
for (inti = 0; i < n; i++) {
if(Place(k, i, x)) {
x[k]= i;
if(k == n - 1) {
for(i = 0; i < n; i++) {
cout<< x[i] << " ";
}
cout<< endl;
}
else{
NQueens(k+ 1, n, x);
}
}
}
}
void NQueens(int n, int *x)
{
NQueens(0,n, x);
}
int main()
{
int x[8];
for (inti = 0; i < 8; i++) {
x[i]= -1;
}
NQueens(8,x);
return 0;
}
2.用回溯法编写一个递归程序解决如下装载问题:有n个集装箱要装上2艘载重分别为c1和c2的轮船,其中集装箱i的重量为wi(1≤i ≤ n),且Σ??≤?1+?2??=1。问是否有合理的装载方案可以将这n个集装箱装上这2艘轮船?如果有,给出装载方案。
举例:当n=3,c1=c2=50,且w=[10,40,40]时,可以将集装箱1和2装到第一艘轮船上,集装箱3装到第二艘轮船上;如果w=[20,40,40]时,无法将这3个集装箱都装上轮船。
源代码:
#include<iostream>
#include<string.h>
usingnamespace std;
template<classT>
classLoading
{
private:
int n,//集装箱数
*x,//当前解
*bestx,//当前最有载重数组
w[100];//集装箱重量数组
T c1,//第一艘轮船的核定载重量
c2,//第二艘轮船的核定载重量
cw,//当前第一艘船的载重量
bestw,//当前第一艘船的最有载重量
r;//剩余集装箱总重量
public:
Loading()
{
c1= 0;
c2= 0;
cw= 0;
r= 0;
bestw= 0;
x= newint[50];
bestx= newint[50];
cout<<"请输入这两艘船的载重:"<< endl;
cin>> c1;
cin>> c2;
cout<<"请输入集装箱个数:"<< endl;
cin>> n;
cout<<"请分别输入各集装箱的载重:"<< endl;
for (int i = 0; i < n;i++)
{
cin>> w[i];
r+= w[i];
}
}
~Loading()
{
delete[]x;
delete[]bestx;
}
void Backtrack(inti);
void Show();
};
template <classT>
voidLoading<T>::Backtrack(inti)
{
if (i > n)
{ //到达叶节点
if (cw > bestw)
{
for (int j = 1; j <=n; j++) bestx[j] = x[j - 1];
bestw= cw;
}
return;
}
//搜索子树
r-= w[i - 1];
if (cw + w[i - 1] <= c1)
{
//搜索左子树
x[i - 1] = 1;
cw+= w[i - 1];
Backtrack(i + 1);
cw-= w[i - 1];
}
if (cw + r >bestw)
{
x[i - 1] = 0;
Backtrack(i + 1);
}
r+= w[i];
}
template <classT>
voidLoading<T>::Show()
{
int i,s = 0;
for (i = 0; i <n; i++)
{
if (bestx[i + 1] ==0)
s+= w[i];
}
if (s<c2)
{
cout<<"最优载重量:";
cout<< bestw << endl;
cout<<"最优的方案为:"<< endl;
cout<<"第一艘船:";
for(i = 1; i <=n; i++)
{
if (bestx[i] == 1)
cout<< i <<"、";
}
cout<<"的装载"<< endl;
cout<<"第二艘船:";
for (i = 1; i <=n; i++)
{
if (bestx[i] == 0)
cout<< i <<"、";
}
cout<<"的装载"<< endl;
}
else
cout<<"c2超载!"<< endl;
}
void main()
{
Loading<int> ld;
ld.Backtrack(1);
ld.Show();
system("pause");
}