A算法解九宫格

以前写拼图游戏的时候就有个疑问:如果随机生成每个图片的位置的话,这个拼图可能是永远也解不出来的。但是当时不知道如何去解一个九宫格问题。

最近了解了一下搜索算法,发现其实很多很多的问题都可以归结为对状态空间树的搜索,搜出来最优解。但是问题的解空间往往是巨大的,超出了计算机的计算能力。搜的所称中如何减少向下搜索的分支非常重要。而启发式搜索算法,着重于先搜那些可能快速达到终点状态的分支,来减少搜索时间。

启发式算法的重点在于如何启发,这是个经验加艺术的技术。启发式算法的启发函数就像是hash表的hash函数一样,设计好了非常牛;空间效率,时间效率都别的算法无可比拟的,甚至说是计算机不可超越的。

练练手,写了一个九宫格的程序。

代码如下(启发函数太简单,复杂情况计算很慢):

//用A*算法解决9宫格问题 // #include<assert.h> #include<iostream> #include<algorithm> #include<time.h> #include<queue> #include<string> #include<vector> using namespace std; int rem[10][2]={{0,0},{0,0},{0,1},{0,2},{1,2},{2,2},{2,1},{2,0},{1,0},{1,1}}; struct Node { char data[3][3]; //记录各个格子里的数字 string key; //当前节点的键值 用以唯一标示一个结点 为简便起见,我们用 data[0][0]+data[[0][1] //+data[0][2]+data[1][0]+...data[2][2]表示 string theWay; //记录父节点如何移动后产生了当前节点 用以输出结果时 向上查找路径 //'1'向左 '2'向右 '3' 向上 '4'向下 int dist; //当前结点里目标结点的“距离” “距离”越小,表示当前结点能通过少量的移动即可达到目标节点 int dept; //当前节点在搜索树种深度 bool moveLeft(string &next) { int i,j; for(i=0;i<3;i++) { for(j=0;j<3;j++) { if(data[i][j]=='9') break; } if(j!=3) break; } if(j>0) //可以左移 { next=key; swap(next[3*i+j],next[3*i+j-1]); return true; } return false; } bool moveRight(string &next) { int i,j; for(i=0;i<3;i++) { for(j=0;j<3;j++) { if(data[i][j]=='9') break; } if(j!=3) break; } if(j<2) //可以右移 { next=key; swap(next[3*i+j],next[3*i+j+1]); return true; } return false; } bool moveDown(string &next) { int i,j; for(i=0;i<3;i++) { for(j=0;j<3;j++) { if(data[i][j]=='9') break; } if(j!=3) break; } if(i<2) //可以下移 { next=key; swap(next[3*i+j],next[3*(i+1)+j]); return true; } return false; } bool moveUp(string &next) { int i,j; for(i=0;i<3;i++) { for(j=0;j<3;j++) { if(data[i][j]=='9') break; } if(j!=3) break; } if(i>0) //可以上移 { next=key; swap(next[3*i+j],next[3*(i-1)+j]); return true; } return false; } bool isFinal() { if(key=="123894765") return true; return false; } friend bool operator < (const Node &node1,const Node &node2) { return node1.dist>node2.dist; } Node(string Key,int depth,string par) { theWay=par; dept=depth; key=Key; for(int i=0;i<9;i++) { data[i/3][i%3]=key[i]; } //计算dist dist=dept; /*for(int i=1;i<9;i++) { if(data[rem[i][0]][rem[i][1]]!='9') { if(data[rem[i][0]][rem[i][1]]+1 != data[rem[i+1][0]][rem[i+1][1]]) dist+=6; } }*/ for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { dist+= abs(i-rem[data[i][j]-'0'][0])+abs(j-rem[data[i][j]-'0'][1]) ; } } } }; class NineBox { private: char *first_key; void input(); void output(Node &final); public: NineBox() { first_key=new char[10]; } ~NineBox() { delete []first_key; } void run(); }; void NineBox::output(Node &final) { int len=final.theWay.length(); for(int i=0;i<len;i++) { switch(final.theWay[i]) { case '1': cout<<"向左->"; break; case '2': cout<<"向右->"; break; case '3': cout<<"向上->" ; break; case '4': cout<<"向下->"; break; } } cout<<"成功!"<<endl; } void NineBox::input( ) { cout<<"请输入九宫格的初始状态字符串:"<<endl; while(cin>>first_key) { char *temp=new char[10]; memcpy(temp,first_key,10); sort(temp,temp+9); int i; for(i=0;i<9;i++) { if(temp[i]!=('1'+i)) break; } if(i==9) break; else { cout<<"输入不合法,请重新输入:"<<endl; } } } void NineBox::run() { priority_queue<Node> open; //未访问过的结点表 vector<string> closed; //访问过的结点表 input(); Node start(first_key,0,""); open.push(start); //放入closed表 closed.push_back(start.key); while(!open.empty()) { Node now=open.top(); open.pop(); if(now.isFinal()) //找到路径 { output(now); return ; } string next=""; if(now.moveLeft(next)) { if(!( find(closed.begin(),closed.end(),next)!=closed.end())) { Node temp(next,now.dept+1,now.theWay+'1'); open.push(temp); closed.push_back(next); } } if(now.moveRight(next)) { if(!( find(closed.begin(),closed.end(),next)!=closed.end())) { Node temp(next,now.dept+1,now.theWay+'2'); open.push(temp); closed.push_back(next); } } if(now.moveUp(next)) { if(!( find(closed.begin(),closed.end(),next)!=closed.end())) { Node temp(next,now.dept+1,now.theWay+'3'); open.push(temp); closed.push_back(next); } } if(now.moveDown(next)) { if(!( find(closed.begin(),closed.end(),next)!=closed.end())) { Node temp(next,now.dept+1,now.theWay+'4'); open.push(temp); closed.push_back(next); } } } } int main() { NineBox *myNineBox=new NineBox(); myNineBox->run(); return 0; }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用递归函数和回溯算法九宫数独问题。以下是一个简单的 Python 代码示例: ```python def solve(board): """ Solve the Sudoku puzzle using recursive backtracking. :param board: 2D list of integers representing the Sudoku puzzle :return: boolean indicating if the puzzle is solved """ empty_cell = find_empty(board) if not empty_cell: return True row, col = empty_cell for num in range(1, 10): if is_valid(board, row, col, num): board[row][col] = num if solve(board): return True board[row][col] = 0 return False def find_empty(board): """ Find an empty cell in the Sudoku puzzle. :param board: 2D list of integers representing the Sudoku puzzle :return: tuple containing the row and column of an empty cell, or None if there are no empty cells """ for row in range(9): for col in range(9): if board[row][col] == 0: return (row, col) return None def is_valid(board, row, col, num): """ Check if a number can be placed in a given cell in the Sudoku puzzle. :param board: 2D list of integers representing the Sudoku puzzle :param row: integer representing the row of the cell to check :param col: integer representing the column of the cell to check :param num: integer representing the number to check :return: boolean indicating if the number can be placed in the cell """ # Check row for i in range(9): if board[row][i] == num: return False # Check column for i in range(9): if board[i][col] == num: return False # Check square square_row = (row // 3) * 3 square_col = (col // 3) * 3 for i in range(square_row, square_row + 3): for j in range(square_col, square_col + 3): if board[i][j] == num: return False return True ``` 使用该函数,您可以通过以下方式调用它: ```python board = [ [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0] ] solve(board) for row in board: print(row) ``` 该代码将打印已决数独的完整板。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值