报恩计划马踏棋盘
//---------------------------------------------------------------------------
/*本文的经典在后半部分。
首先是题目:马踏棋盘问题
设有一个棋盘(2<=n<=50,2<=m<=50),在棋盘上任一点有一个中国象棋“马”
给出马原来的坐标(1,1),问是否可以到达( n,m)。
如果可以则求出最小步数。
不可以则输出error!
规则:马走日字。
看到这个题目,大多数的人会觉得用回溯法是不二之选。可是,它和原来的马踏棋盘问题
又有一定的出入。因为经典的马踏棋盘问题还有一条规则。就是马只能向右走。
所以这道题目的处理量更加大了。在较短的时间内回溯法是绝对得不到解的。
我是个不懂算法的人。我勉强知道有一个算法叫回溯。就我个人先来谈谈如何解题。
因为这道题目比较简单我就直接给出算法了。为了可读性,我用数组时稍微浪费了一点。*/
#pragma hdrstop
#include <iostream.h>
//---------------------------------------------------------------------------
#pragma argsused
void search_(int val,int i,int j,int sz[51][51]);
int main(int argc, char* argv[])
{int sz[51][51]={0};
int i,j,n,m,num;
cin>>n>>m;
sz[1][1]=1;
for (num=1;num<=(n+m);num++)
{
for (i=1;i<=n;i++)
for (j=1;j<=m;j++)
{
search_(sz[i][j],i+1,j+2,sz);
search_(sz[i][j],i+1,j-2,sz);
search_(sz[i][j],i+2,j+1,sz);
search_(sz[i][j],i+2,j-1,sz);
search_(sz[i][j],i-2,j+1,sz);
search_(sz[i][j],i-2,j-1,sz);
search_(sz[i][j],i-1,j+2,sz);
search_(sz[i][j],i-1,j-2,sz);
}
}
--sz[n][m];
if (sz[n][m]!=-1) cout<<sz[n][m];
else cout<<"error!";
getchar();
getchar();
return 0;
}
void search_(int val,int i,int j,int sz[51][51])
{
if ((val!=0)&&(i<=50) && (i>=1) &&(j<=50)&&(j>=1))
if ((sz[i][j]>val)|| (sz[i][j]==0)) sz[i][j]=val+1;
}
//---------------------------------------------------------------------------
/*
上面的讲起来比较麻烦。但就是利用数组下标。表示棋盘。用数值记到达此处的最小步数。
for (num=1;num<=(n+m);num++)这条东西,比较变态。因为下面两条for语句算出来的
不一定是最优解。至少我无法在理论上证明是最优的。我觉得这条for语句可以保证最优。
大家不妨比较一下回溯和我的这个方法的时间效率。
有读者云:回溯可以找到路径,你能吗?
精彩部分现在开始。自己编造了一种颇不错的数据结构。
数组+指针网。我将在以后专门写文章,来说明这种解类似题目,近乎完美的结构。
*/
