代码参考:http://www.cnblogs.com/AdaByron/archive/2011/09/21/2200969.html
本题 BFS,双向BFS,A*超内存,IDA*超时间.....因此本题没有AC
最后总结:这个帖子前前后后补充了很多次插队....
我的结论是每种情况的解不是唯一的(包括最优解也不是唯一的)
就按照题目给的
2 3 4 1 5 x 7 6 8 为例子
题目解:ullddrurdllurrdlurd
dlurullddrurdllurdr
ullddrurdllurdruldr 均可以且都为19步,没法说题目给的解就是最优...
所以出现和题目答案不一样的同学不需要担心你不一定错了,至少我这样认为....
最近由于考试乱七八糟事情,一直没写代码,而且由于这题的一些细节卡了很长时间。
讲道理这题感觉收获很大,至少对于搜索的理解进一步加深。由于不会做A*,所以参考了别人的代码
总体来说思路很简单,但是....细节....还是说下我自己跳进去的坑吧
BFS 和双向BFS很简单不说多少,对于A*算法,之前由于不了解,经过接触后开始其实A*算法并没有啥,它思路就是给搜索方向给点智能性(当然其空间开销是巨大的),因为对于BFS来说搜索的盲目性还是非常大的,它是探索了周围的每一步后由已知推导出最优解,而A*的智能性体现在启发函数上,由于启发函数的存在,导致了探索时,探索的每一步都是可能性最大的,虽然最优解不一定在可能性最大的步骤中,但是由于每一步走可能性最大,所以虽然还没有找到最优解,但是可以说一直在不断的靠近最优解(这就是我理解的所谓的智能性,不在盲目瞎干),例如:搜索的终点在西方的某一处,广搜是利用队列探索每一步的东南西北,四个方向直到找到最优解,而A*,是由于终点在西方,所以我每一步都在不停的往西方探索,虽然还没找到找点,但是不停的在接近......
以上纯属个人理解
//关于IDA* 算法的补充:
2018年12月2日20:12:16 插队
今天写完博客下午又写了IDA*算法,算法给出的步骤结果确实是最优的,但是和答案不一样....同样都在19步内完成的....头疼
2 3 4 1 5 x 7 6 8
ullddrurdllurrdlurd
但是对于我写的IDA*给出的结果确是:
dlurullddrurdllurdr -----汗颜这个步骤我试过了,确实可以将它复原 19步
2018年12月2日21:50:46 插队
结论:其实最优解不唯一.......
开始写了个A*算法一直无法给出最优解...非常的苦恼...一直找不到原因后来发现....(肯本就没想到写个曼哈顿距离这里竟然会出现错误)代码如下:
一共2个错误:
//版本1 没有加括号 减法优先级没有除法高 '1'/3先算
int h(Puzzle p) {//启发函数的曼哈顿距离
int sum = 0;
for (int i = 0; i < N; i++) {
if (p.puzzle[i] == 'x')continue;
if (p.puzzle[i] - '0' != i + 1) {
sum += abs(p.puzzle[i] - '1' / 3 - i / 3) + abs(p.puzzle[i] - '1' - i % 3);
}
}
return sum;
}
//版本2 加了括号第二个abs没有%3
int h(Puzzle p) {//启发函数的曼哈顿距离
int sum = 0;
for (int i = 0; i < N; i++) {
if (p.puzzle[i] == 'x')continue;
if (p.puzzle[i] - '0' != i + 1) {
sum += abs((p.puzzle[i] - '1') / 3 - i / 3) + abs((p.puzzle[i] - '1') - i % 3);
}
}
return sum;
}
//正确的:
int h(Puzzle p) {//启发函数的曼哈顿距离
int sum = 0;
for (int i = 0; i < N; i++) {
if (p.puzzle[i] == 'x')continue;
if (p.puzzle[i] - '0' != i + 1) {
sum += abs((p.puzzle[i] - '1') / 3 - i / 3) + abs((p.puzzle[i] - '1')%3 - i % 3);
}
}
return sum;
}
由于忽略这个启发函数h的第2个错误%3找死我了.....头撞墙的那种懂吗?兄弟
下面的3中代码都没有被AC 原因:Memory Limit Exceeded
思路1:BFS+hash(判重 序列号使用cantor序列)
# include<iostream>
# include<string>
# include<queue>
#define N 9
using namespace std;
bool visited[370000];
string path[370000];
const int fac[] = { 1,1,2,6,24,120,720,5040,40320 };//康托序列
int dri[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };//东 南 西 北
char por[4] = { 'l','u','r','d' };
struct Xpoint {
int x;
int y;
};
struct Pulzzle {
char puzzle[9];//内部标记数组
Xpoint Xpoint;
}StartPoint, EndPoint;
queue<Pulzzle> q;
bool IsOK(Pulzzle&p) {
for (int i = 0; i < N-1; i++) {
if (p.puzzle[i]-'0' != i + 1)
return false;
}
return true;
}
int Cantor(Pulzzle&p) {
int i, ii, n, sum = 0;
for (i = 0; i < N; ++i) {
n = 0;
for (ii = i + 1; ii < N; ii++) {
if (p.puzzle[ii] < p.puzzle[i])
n++;
}
sum += n*fac[N - i - 1];
}
return sum;
}
void BFS(Pulzzle p) {
visited[0] = 1;//终点记录被访问
path[0] = "";
q.push(p);//入队
Pulzzle tp;
int cantorValue;
while (!q.empty()) {
p = q.front();
q.pop();
tp = p;
for (int i = 0; i < 4; ++i) {
tp.Xpoint.x += dri[i][0];
tp.Xpoint.y += dri[i][1];
if ((tp.Xpoint.x >= 0 && tp.Xpoint.x < 3) && (tp.Xpoint.y >= 0 && tp.Xpoint.y < 3)) {//在范围内
tp.puzzle[p.Xpoint.x * 3 + p.Xpoint.y] = tp.puzzle[tp.Xpoint.x * 3 + tp.Xpoint.y];//原位置补现位置数
tp.puzzle[tp.Xpoint.x * 3 + tp.Xpoint.y] = 'x';//现位置为 x
cantorValue = Cantor(tp);
if (!visited[cantorValue]) {
path[cantorValue] = path[Cantor(p)] + por[i];
q.push(tp);
visited[cantorValue] = 1;
}
}
tp = p;
}//四种方向记录
}
}
int main(void) {
int CantorValue;
for (int i = 0; i < N; ++i) {
EndPoint.puzzle[i] = (i + 1) + '0';
}
EndPoint.puzzle[8] = 'x';
EndPoint.Xpoint.x = 2;
EndPoint.Xpoint.y = 2;
while (1) {
for (int i = 0; i < N; ++i) {
cin >> StartPoint.puzzle[i];
if (StartPoint.puzzle[i] == 'x') {
StartPoint.Xpoint.x = i / 3;
StartPoint.Xpoint.y = i % 3;
}
}//录入地图
CantorValue=Cantor(StartPoint);//拿到起始点的康拓值
memset(visited, 0, sizeof(visited));//访问表全部初始化0
BFS(EndPoint);//广搜末尾的所有情况
if (!visited[CantorValue]) {
cout << "unsolvable" << endl;
}
else {
for(int i=path[CantorValue].length()-1;i>=0;i--)
cout << path[CantorValue][i];
}
}
system("pause");
return 0;
}
思路2:双向BFS(起点和终点已知)+hash(判重 cantor序列)+逆序数对奇偶性不变(情况可行性判断)
# include<iostream>
# include<string>
# include<queue>
#define N 9
using namespace std;
bool flag;
int visited[370000];
string path[370000];
const int fac[] = { 1,1,2,6,24,120,720,5040,40320 };//康托序列
int dri[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };//东 南 西 北
char negative_dir[4] = { 'l','u','r','d' };//方向与dri相反
char positive_dir[4] = { 'r','d','l','u' };//方向与dri东南西北对应右下左上
string result;
struct p {
int x, y;
};
struct Puzzle {
char puzzle[N];
p Point;
}StartPoint,EndPoint;
queue<Puzzle> pq;//正序队列 startpoint开始
queue<Puzzle> nq;//逆序队列 endpoint开始
int Cantor(Puzzle p) {
int i, j, n, sum=0;
for (i = 0; i < N; i++) {
n = 0;
for (j = i + 1; j < N; j++) {
if (p.puzzle[j] < p.puzzle[i])
n++;
}
sum += fac[8 - i] * n;
}
return sum;
}
void BFS(void) {
int cantorValue;
Puzzle p, tp;
p = pq.front();
tp = p;
pq.pop();
for (int i = 0; i < 4; ++i) {//四向搜索
tp.Point.x += dri[i][0];
tp.Point.y += dri[i][1];
if ((tp.Point.x >= 0 && tp.Point.x < 3) && (tp.Point.y >= 0 && tp.Point.y < 3)) {//在范围内
tp.puzzle[p.Point.x * 3 + p.Point.y] = tp.puzzle[tp.Point.x * 3 + tp.Point.y];
tp.puzzle[tp.Point.x * 3 + tp.Point.y] = 'x';
cantorValue = Cantor(tp);
if (!visited[cantorValue]) {
pq.push(tp);
visited[cantorValue] = 1;//正序访问
path[cantorValue] = path[Cantor(p)] + positive_dir[i];
}
else {//已经被访问
if (visited[cantorValue] == 2) {//正反搜索接触到了
flag = true;//找到了
reverse(path[cantorValue].begin(), path[cantorValue].end());
result = path[Cantor(p)] + path[cantorValue];
return;
}//else就是自己正向重复遍历
}
}
tp = p;
}
}
void ReBFS(void) {
int cantorValue;
Puzzle p, tp;
p = nq.front();
tp = p;
nq.pop();
for (int i = 0; i < 4; ++i) {//四向搜索
tp.Point.x += dri[i][0];
tp.Point.y += dri[i][1];
if ((tp.Point.x >= 0 && tp.Point.x < 3) && (tp.Point.y >= 0 && tp.Point.y < 3)) {//在范围内
tp.puzzle[p.Point.x * 3 + p.Point.y] = tp.puzzle[tp.Point.x * 3 + tp.Point.y];
tp.puzzle[tp.Point.x * 3 + tp.Point.y] = 'x';
cantorValue = Cantor(tp);
if (!visited[cantorValue]) {
nq.push(tp);
visited[cantorValue] = 2;//逆序访问
path[cantorValue] = path[Cantor(p)] +negative_dir[i];
}
else {//已经被访问
if (visited[cantorValue] == 1) {//正反搜索接触到了
flag = true;//找到了
reverse(path[Cantor(p)].begin(), path[Cantor(p)].end());
result = path[cantorValue] + path[Cantor(p)];
return;
}//else就是自己正向重复遍历
}
}
tp = p;
}
}
bool ISOK(Puzzle p) {//判定标准逆序奇偶性不变
int i,j,n=0;
for (i = 0; i < N; i++) {
if (p.puzzle[i] == 'x') continue;
for (j = i - 1; j >= 0; j--) {
if (p.puzzle[j] == 'x') continue;
if (p.puzzle[j] < p.puzzle[i])
n++;
}
}
return n & 1 ? false : true;
}
int main(void) {
int CantorValue;
for (int i = 0; i < N; i++) {
EndPoint.puzzle[i] = i + 1+'0';
}
EndPoint.puzzle[8] = 'x';
EndPoint.Point.x = EndPoint.Point.y = 2;
while (1) {
for (int i = 0; i < N; i++) {
cin >> StartPoint.puzzle[i];
if (StartPoint.puzzle[i] == 'x') {
StartPoint.Point.x = i / 3;
StartPoint.Point.y = i % 3;
}
}//录入起始点的信息
//------------------------------------------
result = "";
CantorValue = Cantor(StartPoint);
path[CantorValue] = path[0] = "";
flag = false;
memset(visited, 0, sizeof(visited));//访问表初始化为0
memset(path, 0, sizeof(path));//初始化路径表
//--------------------------------------------
if (!ISOK(StartPoint)) {
cout << "unsolvable" << endl;
}
pq.push(StartPoint);
nq.push(EndPoint);//正负队列入队
int qnum;
while (!flag) {
qnum = pq.size();
if (!flag&&qnum--)
BFS();
qnum = nq.size();
if (!flag&&qnum--)
ReBFS();
}
cout << result << endl;//输出结果
}
system("pause");
return 0;
}
思路3:Astar算法+hash(cantor序列判重)+逆序数对奇偶性不变(判断)+启发函数h(曼哈顿距离)
# include<iostream>
# include<string>
# include<queue>
#define N 9
using namespace std;
struct p {
int x, y;
};
class Puzzle {
public:
char puzzle[N];
p Point;//二维数组中的点
int f, g;//启发函数 f=g+h
Puzzle() { ; }
}StartPoint, EndPoint;
class cmp{
public:
bool operator()(Puzzle a,Puzzle b) {
return a.f > b.f;
}
};
bool visited[370000];//判断是否访问
string path[370000];//记录每种情况到起点情况的路径
const int fac[] = { 1,1,2,6,24,120,720,5040,40320 };//康托序列
//--------------顺时针
int dri[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };//东 南 西 北
char positive_dir[4] = { 'r','d','l','u' };//方向与dri东南西北对应右下左上
//--------------逆时针
//const int dri[4][2] = { { 1,0 },{ 0,1 },{ -1,0 },{ 0,-1 } };//四个方向
//const char positive_dir[4] = { 'd','r','u','l' };//对应走法
string result;
priority_queue<Puzzle, vector<Puzzle>,cmp>pq;//定义一个优先队列
int abs(int a) {
return a > 0 ? a : -a;
}
int h(Puzzle p) {//启发函数的曼哈顿距离
int sum = 0;
for (int i = 0; i < N; i++) {
if (p.puzzle[i] == 'x')continue;
if (p.puzzle[i] - '0' != i + 1) {
sum += abs((p.puzzle[i] - '1') / 3 - i / 3) + abs((p.puzzle[i] - '1') %3- i % 3);
}
}
return sum;
}
int Cantor(Puzzle p) {//计算康拓值用于hash判重
int i, j, n, sum = 0;
for (i = 0; i < N; i++) {
n = 0;
for (j = i + 1; j < N; j++) {
if (p.puzzle[j] < p.puzzle[i])
n++;
}
sum += fac[8 - i] * n;
}
return sum;
}
bool ISOK(Puzzle p) {//判定标准逆序奇偶性不变 (判断输入八数码是否有解)
int i, j, n = 0;
for (i = 0; i < N; i++) {
if (p.puzzle[i] == 'x') continue;
for (j = i - 1; j >= 0; j--) {
if (p.puzzle[j] == 'x') continue;
if (p.puzzle[j] < p.puzzle[i])
n++;
}
}
return n & 1 ? false : true;
}
void Astar(void) {
Puzzle p, tp;
int cantorValue;
while (!pq.empty()) {
tp = p = pq.top();
pq.pop();
for (int i = 0; i < 4; i++) {
tp.Point.x += dri[i][0];
tp.Point.y += dri[i][1];
if ((tp.Point.x >= 0 && tp.Point.x < 3) && (tp.Point.y >= 0 && tp.Point.y < 3)) {//在范围内
tp.puzzle[p.Point.x * 3 + p.Point.y] = tp.puzzle[tp.Point.x * 3 + tp.Point.y];
tp.puzzle[tp.Point.x * 3 + tp.Point.y] = 'x';//空白和移动的点交换数据
cantorValue = Cantor(tp);//计算临时电的康拓值
if (!visited[cantorValue]) {//未被访问过
tp.g++;//g度加1
tp.f = tp.g + h(tp);//拿到启发函数f 用于优先队列判断
pq.push(tp);
visited[cantorValue] = true;//当前标记访问
path[cantorValue] = path[Cantor(p)] + positive_dir[i];//路径记录
if (!cantorValue) {//到达终点情况
result = path[0];
return;
}
}
}
tp = p;//回溯p点位置
}
}
}
int main(void) {
int CantorValue;
for (int i = 0; i < N; i++) {
EndPoint.puzzle[i] = i + 1 + '0';
}
EndPoint.puzzle[8] = 'x';
EndPoint.Point.x = EndPoint.Point.y = 2;
//初始化结束状态
while (1) {
while (!pq.empty()) {
pq.pop();
}//清空队列为下一次做准备
for (int i = 0; i < N; i++) {
cin >> StartPoint.puzzle[i];
if (StartPoint.puzzle[i] == 'x') {
StartPoint.Point.x = i / 3;
StartPoint.Point.y = i % 3;
}
}//录入起始点的信息
memset(visited, 0, sizeof(visited));//访问表初始化为0
memset(path, 0, sizeof(path));//初始化路径表
CantorValue = Cantor(StartPoint);//计算起始点康拓值
path[CantorValue] = "";
if (!ISOK(StartPoint)) {
cout << "unsolvable" << endl;
}
StartPoint.g = 0;
StartPoint.f = StartPoint.g + h(StartPoint);
pq.push(StartPoint);
visited[CantorValue] = 1;//起始点标记访问
Astar();
cout << result << endl;//输出结果
}
system("pause");
return 0;
}
利用pre和op来记录路径
# include<iostream>
# include<string>
# include<stack>
# include<queue>
#define N 9
#define NMAX 362885
using namespace std;
struct p {
int x, y;
};
class Puzzle {
public:
char puzzle[N];
p Point;//二维数组中的点
int f, g;//启发函数 f=g+h
Puzzle() { ; }
}StartPoint, EndPoint;
class cmp {
public:
bool operator()(Puzzle a, Puzzle b) {
return a.f > b.f;
}
};
bool visited[NMAX];//判断是否访问
const int fac[] = { 1,1,2,6,24,120,720,5040,40320 };//康托序列
int dri[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };//东 南 西 北
char positive_dir[4] = { 'r','d','l','u' };//方向与dri东南西北对应右下左上
char op[NMAX];
int pre[NMAX];
stack<char>s;
priority_queue<Puzzle, vector<Puzzle>, cmp>pq;//定义一个优先队列
int abs(int a) {
return a > 0 ? a : -a;
}
int h(Puzzle p) {//启发函数的曼哈顿距离
int sum = 0;
int c;
for (int i = 0; i < N; i++) {
if (p.puzzle[i] == 'x')continue;
c = p.puzzle[i] - '0';
if ( c!= i + 1) {
sum += abs((c-1) / 3 - i / 3) + abs((c-1) % 3 - i % 3);
}
}
return sum;
}
int Cantor(Puzzle p) {//计算康拓值用于hash判重
int i, j, n, sum = 0;
for (i = 0; i < N; i++) {
n = 0;
for (j = i + 1; j < N; j++) {
if (p.puzzle[j] < p.puzzle[i])
n++;
}
sum += fac[8 - i] * n;
}
return sum;
}
bool ISOK(Puzzle p) {//判定标准逆序奇偶性不变 (判断输入八数码是否有解)
int i, j, n = 0;
for (i = 0; i < N; i++) {
if (p.puzzle[i] == 'x') continue;
for (j = i - 1; j >= 0; j--) {
if (p.puzzle[j] == 'x') continue;
if (p.puzzle[j] < p.puzzle[i])
n++;
}
}
return n & 1 ? false : true;
}
void Astar(void) {
Puzzle p, tp;
int cantorValue;
while (!pq.empty()) {
tp = p = pq.top();
pq.pop();
for (int i = 0; i < 4; i++) {
tp.Point.x += dri[i][0];
tp.Point.y += dri[i][1];
if ((tp.Point.x >= 0 && tp.Point.x < 3) && (tp.Point.y >= 0 && tp.Point.y < 3)) {//在范围内
tp.puzzle[p.Point.x * 3 + p.Point.y] = tp.puzzle[tp.Point.x * 3 + tp.Point.y];
tp.puzzle[tp.Point.x * 3 + tp.Point.y] = 'x';//空白和移动的点交换数据
cantorValue = Cantor(tp);//计算临时电的康拓值
if (!visited[cantorValue]) {//未被访问过
tp.g++;//g度加1
tp.f = tp.g + h(tp);//拿到启发函数f 用于优先队列判断
pq.push(tp);
visited[cantorValue] = true;//当前标记访问
pre[cantorValue] = Cantor(p);
op[cantorValue] = positive_dir[i];
if (!cantorValue) return;
}
}
tp = p;//回溯p点位置
}
}
}
int main(void) {
int CantorValue;
for (int i = 0; i < N; i++) {
EndPoint.puzzle[i] = i + 1 + '0';
}
EndPoint.puzzle[8] = 'x';
EndPoint.Point.x = EndPoint.Point.y = 2;
//初始化结束状态
while (1) {
while (!pq.empty()) {
pq.pop();
}//清空队列为下一次做准备
for (int i = 0; i < N; i++) {
cin >> StartPoint.puzzle[i];
if (StartPoint.puzzle[i] == 'x') {
StartPoint.Point.x = i / 3;
StartPoint.Point.y = i % 3;
}
}//录入起始点的信息
memset(visited, 0, sizeof(visited));//访问表初始化为0
CantorValue = Cantor(StartPoint);//计算起始点康拓值
if (!ISOK(StartPoint)) {
cout << "unsolvable" << endl;
}
StartPoint.g = 0;
StartPoint.f = h(StartPoint);
pq.push(StartPoint);
visited[CantorValue] = 1;//起始点标记访问
Astar();
int index;
for (index = 0; index != CantorValue; index = pre[index])
s.push(op[index]);
while (!s.empty()) {
cout << s.top();
s.pop();
}
}
system("pause");
return 0;
}
思路4:IDAstar 算法算出了2个答案比较汗颜 = =。貌似我是第一个遇到这个问题的,这题竟然2解
#include <iostream>
#define N 9
#define NMAX 362885
using namespace std;
struct p {
int x, y;
};
class Puzzle {
public:
char puzzle[N];
p Point;//二维数组中的点
Puzzle() { ; }
}StartPoint, EndPoint;
bool falg;
int Deep;
int index;
char op[NMAX];
int dri[4][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,0 } };//东 南 西 北
char positive_dir[4] = { 'r','d','l','u' };//方向与dri东南西北对应右下左上
int abs(int a) {
return a > 0 ? a : -a;
}
int h(Puzzle p) {//启发函数的曼哈顿距离
int sum = 0;
for (int i = 0; i < N; i++) {
if (p.puzzle[i] == 'x')continue;
if (p.puzzle[i] - '0' != i + 1) {
sum += abs((p.puzzle[i] - '1') / 3 - i / 3) + abs((p.puzzle[i] - '1') % 3 - i % 3);
}
}
return sum;
}
bool ISOK(Puzzle p) {//判定标准逆序奇偶性不变 (判断输入八数码是否有解)
int i, j, n = 0;
for (i = 0; i < N; i++) {
if (p.puzzle[i] == 'x') continue;
for (j = i - 1; j >= 0; j--) {
if (p.puzzle[j] == 'x') continue;
if (p.puzzle[j] < p.puzzle[i])
n++;
}
}
return n & 1 ? false : true;
}
void DFS(int curDeep,Puzzle p) {
int deep;
Puzzle tp=p;
for (int i = 0; i < 4; i++, tp = p) {
tp.Point.x += dri[i][0];
tp.Point.y += dri[i][1];
if ((tp.Point.x >= 0 && tp.Point.x < 3) && (tp.Point.y >= 0 && tp.Point.y < 3)) {//在范围内
tp.puzzle[p.Point.x * 3 + p.Point.y] = tp.puzzle[tp.Point.x * 3 + tp.Point.y];
tp.puzzle[tp.Point.x * 3 + tp.Point.y] = 'x';//空白和移动的点交换数据
deep = h(tp);//拿到临时点deep
//检查是否需要剪枝
if (curDeep + deep>Deep) continue;//进行剪枝
op[index++] = positive_dir[i];
if (deep == 0) {
falg = true; return;
}
DFS(curDeep + 1, tp);
if (falg) return;
index--;
}
}
}
int main(void) {
for (int i = 0; i < N; i++) {
EndPoint.puzzle[i] = i + 1 + '0';
}
EndPoint.puzzle[8] = 'x';
EndPoint.Point.x = EndPoint.Point.y = 2;
//初始化结束状态
while (1) {
falg = false;
index = 0;
for (int i = 0; i < N; i++) {
cin >> StartPoint.puzzle[i];
if (StartPoint.puzzle[i] == 'x') {
StartPoint.Point.x = i / 3;
StartPoint.Point.y = i % 3;
}
}//录入起始点的信息
if (!ISOK(StartPoint)) {
cout << "unsolvable" << endl;
continue;
}//初始情况判断
Deep = h(StartPoint);//拿到起始点的深度
while (!falg) {
DFS(0, StartPoint);
Deep++;
}
for (int i = 0; i < index; i++)
cout << op[i];
cout << endl;
}
system("pause");
return 0;
}