马跳棋盘的程序,基本的回溯法搜索路径,效率很低。
在路径的打印上,1-n的数字分别代表了每步应该调到的位置。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<stdio.h>
#include<vector>
using namespace std;
#define SIZE 10
struct position
{
int x,y;
}temp;
/* “日” 字 跳法 */
int dx[] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[] = { 1, 2, 2, 1, -1, -2, -2, -1};
/*定义棋盘是否被访问*/
int vis[SIZE+1][SIZE+1];
/*定义棋盘*/
int map[SIZE+1][SIZE+1];
/*保存路径*/
vector<position> path;
int ans;//记录数量
void solve( int x, int y, int num ,int n)
{
int i,j;
if( num == n*n )//找到一个可行解
{
ans += 1;//解数量+1
for( i = 0 ; i < path.size() - 1 ; i++ )
{
map[path[i].x][path[i].y] = i + 1;
}
map[path[path.size()-1].x][path[path.size()-1].y] = i+1;
for( i = 1 ; i <= n ; i++)
{
for( j = 1 ; j <= n ; j++)
{
printf("%3d ",map[i][j]);
}
puts("");
}
printf("继续?");
system("pause");
}
int nextX, nextY;
for( i = 0 ; i < 7 ; i++ )
{
nextX = x + dx[i];
nextY = y + dy[i];
if( nextX <= n && nextX >= 1 && nextY <=n && nextY >= 1 && !vis[nextX][nextY] )
{
temp.x = nextX;
temp.y = nextY;
vis[nextX][nextY] = 1;//标记被访问点
path.push_back(temp);//记录path
solve( nextX, nextY, num+1, n);//寻找下一个点
vis[nextX][nextY] = 0;
path.pop_back();//弹出最后一个元素
}
}
}
int main()
{
int n;//棋盘大小
int Xstart,Ystart;
puts("请输入棋盘大小 n (1~10) (n=-1退出):");
while( scanf("%d", &n) == 1 && n != -1 )
{
while( !( n <= 10 && n >= 1 ) )
{
puts("棋盘大小输入错误,请重新输入(范围1~10)");
scanf("%d",&n);
if( n == -1 ) return 0;
}
ans = 0;
memset(vis, 0, sizeof(vis));
memset(map, 0, sizeof(map));
path.clear();
puts("请输入开始探索的起始位置 x,y (范围1-n):");
scanf("%d,%d", &Xstart, &Ystart);
while( !( Xstart <= n && Xstart >= 1 && Ystart >= 1 && Ystart <= n ) )
{
puts("坐标输入错误,请重新输入(范围1-n)");
scanf("%d,%d", &Xstart, &Ystart);
}
vis[Xstart][Ystart] = 1;
map[Xstart][Ystart] = 1;
temp.x = Xstart; temp.y = Ystart;
path.push_back(temp);
solve( Xstart, Ystart, 1, n);//work to solve this problem
printf("本次搜索共发现了%d个可行解\n\n", ans);
puts("请输入棋盘大小n(n=-1退出):");
}
}