用的是c++,c语言也能懂
先放题目吧(题目直接截图了嘿嘿嘿,方便快捷)
样例输入
Input Sample 1:
3 3
001
100
110
Input Sample 2:
3 3
000
000
000
样例输出
Output Sample 1:
4
RDRD
Output Sample 2:
4
DDRR
数据规模和约定
有20%的数据满足:1<=n,m<=10
有50%的数据满足:1<=n,m<=50
有100%的数据满足:1<=n,m<=500。
- 思路
这题是bfs的模板,状态转移是上下左右四个方向,套用一个循环,满足条件的入队列,有什么条件呢?第一个条件是下一步要走的地方没有障碍,也就是非‘1’(对应代码mazz[t1][t2]!='1');第二个条件是每一次上下左右都要保证在0~n和0~m的范围内(WA了一次后才发现这个问题呀呀呀);然后我对每一次搜素都做了标记(vis[][]标记数组),这样搜到的以后在遇到就避免重复判断。
这题我觉得比较新颖的是还要输出路径,当时也只是套完板子再来思考这个问题的,方法有很多,但我觉得string是真的简洁方便。只要在结构体里多加一个string,每一步都多加一个方向(方向的顺序按字典序排列,一旦找到目标位置,直接结束输出一定就是满足题意得答案),没错string可以直接做加法处理,结果就是把你加上得字符加到原来得字符串里,这是这题里学到得新知识嘿嘿嘿!
下面直接贴源代码。
#include<bits/stdc++.h>
using namespace std;
int n,m;
char mazz[550][550];
int vis[550][550];
int dx[4]={1,0,0,-1};
int dy[4]={0,-1,1,0};
char r[10]={'D','L','R','U'};
struct pos{
int row;
int col;
int step;
string s;
};
void bfs()
{
pos cur,now;
cur.s="";
cur.row=1;
cur.col=1;
vis[1][1]=1;
cur.step=0;
queue<pos> q;
q.push(cur);
while(!q.empty())
{
cur=q.front();
q.pop();
if(cur.row==n && cur.col==m)
{
cout<<cur.step<<endl;
cout<<cur.s;
return ;
}
for(int i=0;i<4;i++)
{
int t1=cur.row+dx[i];
int t2=cur.col+dy[i];
if((t1>=1&&t1<=n) && (t2>=1&&t2<=m) && mazz[t1][t2]!='1' && vis[t1][t2]==0)
{
vis[t1][t2]=1;
now.row=t1;
now.col=t2;
now.step=cur.step+1;
now.s=cur.s+r[i];
q.push(now);
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>mazz[i][j];
if(mazz[i][j]=='1') vis[i][j]=1;
}
}
bfs();
return 0;
}
- 总结
如果不懂bfs,建议先去从简单的题目入手,比如洛谷里“奇怪的电梯”那道题,更便于理解,然后懂了再做提升,其实区别也就是状态转移的方向变多了,对于初学可能会一下子接受不了。然后是做题不仅只是追求AC通过,而是在练题的这个过程中不断学习更简便的方法,锻炼自己的思维,提升代码能力和思考问题解决问题的效率。