题目:
给定一个n*m的矩阵,求每个0距离任意的1的最短距离
这里的距离定义为曼哈顿距离,即|x| + |y|
Input
第一行两个整数n,m。 (1 <= n,m <= 1000)
接下来一个N行M列的01矩阵,数字之间没有空格。
Output
一个N行M列的矩阵,相邻两个整数之间用一个空格隔开。
Sample Input 1
4 4
0010
1001
1000
0000
Sample Output 1
1 1 0 1
0 1 1 0
0 1 2 1
1 2 3 2
反思:
我发现我每学会一个算法,就总是习惯使用那种最常规的框架,框架尽管能让我对题目有一个大体的方向,但这也是有弊端的我觉得,这容易让我有一种定性思维,每次都那么做,这其实是不太好的我个人认为。再者,我觉得,一类题一个是多做同种类型的;再就是,多总结反思可以灵活运用各个题之间的代码思路相互结合,这点我做的还是不够好。我做的题还是少啊。
这道题我开始是用的常规思路,就是以每个 0 为起点,逐个bfs,找到最近的1就结束,尽管这个思路是对的,但是在这么大的数据量下,又结合入栈出栈,不难想到一定会超时
我开始写的代码:
#include"iostream"
#include"queue"
#include"cstring"
using namespace std;
int n, m, g;
int a[1005][1005];
int xx[4] = {-1,0,1,0}, yy[4]= {0,1,0,-1};
int vis[1005][1005];
struct point{
int x,y,step;
point(int xx,int yy,int ss){
x = xx;
y = yy;
step = ss;
}
};
void bfs(int cx,int cy){
queue<point> q;
q.push(point(cx,cy,0));
vis[cx][cy] = 1;
while(!q.empty()){
point p = q.front();
q.pop();
if(a[p.x][p.y] == 1){
g = p.step;
return;
}
for(int i = 0;i < 4;i ++){
int tx = p.x + xx[i];
int ty = p.y + yy[i];
if(vis[tx][ty] != 1 && tx>= 0 && tx <n && ty >= 0 && ty < m){
vis[tx][ty] = 1;
q.push(point(tx,ty,p.step+1));
}
}
}
}
int main(){
cin >> n >> m;
string s;
for(int i = 0;i < n;i ++){
cin >> s;
for(int j = 0;j < m;j ++){
a[i][j] = s[j]-48;
}
}
for(int i = 0;i < n;i ++){
for(int j = 0;j < m;j ++){
if(a[i][j] == 1) cout << 0 << " ";
else{
memset(vis,0,sizeof(vis));
bfs(i,j);
cout << g << " ";
}
}
cout << endl;
}
return 0;
}
尽管说我在这上面做了一些优化,但是是远远不够的。
借鉴大佬的代码:
#include"iostream"
#include"utility" // pair 的头文件
#include"queue"
#include"cstring"
using namespace std;
int n, m;
int xx[4] = {-1,0,1,0}, yy[4]={0,1,0,-1};
int a[1005][1005];
int dist[1005][1005];
pair<int,int> cur;
queue<pair<int,int> > q;
int main(){
cin >> n >> m;
string s;
memset(dist,-1,sizeof(dist));
for(int i = 0;i < n;i ++){
cin >> s;
for(int j = 0;j < m;j ++){
if(s[j] == '1'){
q.push(make_pair(i,j));
dist[i][j] = 0;
}
}
}
while(!q.empty()){
cur = q.front();
q.pop();
for(int i = 0;i < 4;i ++){
int tx = cur.first + xx[i];
int ty = cur.second + yy[i];
if(tx>=0 && tx<n && ty>=0 && ty<m && dist[tx][ty] == -1){
dist[tx][ty] = dist[cur.first][cur.second] + 1; // 此时的dist[cur.first][cur.second]在开始是为0的 这里的理解要对应到输入是的 s[j] == '1' 的判断那里
q.push(make_pair(tx,ty));
}
}
}
for(int i = 0;i < n;i ++){
for(int j = 0;j < m;j ++){
cout << dist[i][j] << " ";
}
cout<< endl;
}
return 0;
}
大佬的代码值得借鉴的地方:
1.首先是他的解题思想,很好,是从1开始bfs,但是一般我感觉首先容易想到的是bfs 0(尽管超时),在我看来这就是思想上的进步,每次做题的时候就应该事先多考虑一下,到底先对谁bfs更好,这一点真的很重要,会少走不少弯路。
2.他的bfs的写作模板也是值得借鉴的,我之前写bfs总是习惯于另外再写一个方法,不过今天看了他的代码我觉得以后我也可以尝试一下他的这种风格。
世界很大,一个家很小,但有一点是一样的,唯有爱能让它变得更好。