马的遍历
首先,这是一道水题。(虽然我提交了四次才A掉)
思路是很简单的。马的遍历,经典中的经典,一想就是搜索。但流传较广的是DFS,第一直觉也是DFS。可是,一看题,求马到各点的最短路,是求最优解,且是各个点,自然想到了BFS。
BFS的简单思路,将矩阵每个点赋值为-1,先定义一个队列,用两个数组表示,h(行),l(列)。
下面从马的坐标开始向外跳,判断是否超出边界,且是否已跳到过(相当于>-1),若大于-1,根据BFS越先越优的性质,跳过搜索下一个。最后,定义指针head,tail指向队头队尾。
见代码:
#include<iostream> #include<cstring> using namespace std; void bfs(); int head,tail=1,b,c,m,n,a[401][401]; int p[9]={0,-2,-2,-1,-1,1,1,2,2}; int y[9]={0,-1,1,-2,2,-2,2,-1,1}; int h[160001],l[160001]; int main() { cin>>m>>n>>b>>c; memset(a,-1,sizeof(a)); a[b][c]=0; h[1]=b; l[1]=c; bfs(); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) cout<<a[i][j]<<" "; cout<<endl; } return 0; } void bfs() { while(head!=tail) { head++; for(int i=1;i<=8;i++) { if(h[head]+p[i]>0&&h[head]+p[i]<1+m&&l[head]+y[i]>0&&y[i]+l[head]<1+n&&a[h[head]+p[i]][l[head]+y[i]]==-1) { a[h[head]+p[i]][l[head]+y[i]]=a[h[head]][l[head]]+1; tail++; h[tail]=h[head]+p[i]; l[tail]=l[head]+y[i]; } } } }
然后……华丽丽地挂掉啦!!!
原因是未设域宽。
于是,见代码*2:
#include<iostream> #include<cstring> #include<iomanip> using namespace std; void bfs(); int head,tail=1,b,c,m,n,a[401][401]; int p[9]={0,-2,-2,-1,-1,1,1,2,2}; int y[9]={0,-1,1,-2,2,-2,2,-1,1}; int h[160001],l[160001]; int main() { cin>>m>>n>>b>>c; memset(a,-1,sizeof(a)); a[b][c]=0; h[1]=b; l[1]=c; bfs(); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) if(j>1) cout<<setw(5)<<a[i][j]; else cout<<a[i][j]; cout<<endl; } return 0; } void bfs() { while(head!=tail) { head++; for(int i=1;i<=8;i++) { if(h[head]+p[i]>0&&h[head]+p[i]<1+m&&l[head]+y[i]>0&&y[i]+l[head]<1+n&&a[h[head]+p[i]][l[head]+y[i]]==-1) { a[h[head]+p[i]][l[head]+y[i]]=a[h[head]][l[head]]+1; tail++; h[tail]=h[head]+p[i]; l[tail]=l[head]+y[i]; } } } }
又挂啦!左对齐!
于是学到了一个神器——std::left——自动左对齐。(当然可为std::right,自动右对齐)调用<iomanip>库,在setw前输入即可。
见代码*3:
#include<iostream> #include<cstring> #include<iomanip> using namespace std; void bfs(); int head,tail=1,b,c,m,n,a[401][401]; int p[9]={0,-2,-2,-1,-1,1,1,2,2}; int y[9]={0,-1,1,-2,2,-2,2,-1,1}; int h[160001],l[160001]; int main() { cin>>m>>n>>b>>c; memset(a,-1,sizeof(a)); a[b][c]=0; h[1]=b; l[1]=c; bfs(); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) { if(j>1) cout<<std::left<<setw(5)<<a[i][j]; else cout<<std::left<<setw(5)<<a[i][j]; } cout<<endl; } return 0; } void bfs() { while(head!=tail) { head++; for(int i=1;i<=8;i++) { if(h[head]+p[i]>0&&h[head]+p[i]<1+m&&l[head]+y[i]>0&&y[i]+l[head]<1+n&&a[h[head]+p[i]][l[head]+y[i]]==-1) { a[h[head]+p[i]][l[head]+y[i]]=a[h[head]][l[head]]+1; tail++; h[tail]=h[head]+p[i]; l[tail]=l[head]+y[i]; } } } }
满分啦!好开心!!!
例行总结:联系了BFS,学到了新神器,还明白了要注意域宽。