位图
时间限制: 1 Sec
内存限制: 64 MB
题目描述
给出一个大小为n行*m列的矩形位图。该位图的每一个象素点不是白色就是黑色,但是至少有一个象素点是白色。在i行j列的象素点我们称为点(i,j)。两个象素点p1=(i1,j1)和p2=(i2,j2)之间的距离定义如下:
d(p1,p2)=|i1-i2|+|j1-j2|.
现在的任务是:对于每一个象素点,计算它到最近的白色点的距离。如果它本身是白色点,距离为0。
输入
第1行:2个整数n,m(1<=n <=182,1<=m<=182)
接下来n行,每一行有一个长度为m的0/1字符串,描述一行象素点。如果点(i,j)为白色,则值为1,否则值为0。
输出
共n行,每行有m个整数,数之间用1个空格分开,分别表示对应的象素点距离白色点的距离。
样例输入
3 4
0001
0011
0110
样例输出
3 2 1 0
2 1 0 0
1 0 0 1
解析
这道题大多数同学都是用搜索来完成的,那么我们首先来讲述一下搜索该如何进行。思路如下:我们可以从1开始搜,只不过用了SPFA的思想,即如果成功更新ans[i][j];那么才继续搜。
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int n,m;int a[155][155];
int ans[155][155];
int mx[4]={0,0,1,-1},my[4]={1,-1,0,0};
int qx[150*151],qy[150*151];
int main(){
memset(ans,60,sizeof(ans));
scanf("%d%d",&n,&m);int head=0,tail=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
if(a[i][j]){
ans[i][j]=0;
qx[++tail]=i;qy[tail]=j;
————————————————>把1先扔进队列
}
}
}
int x,y;
while(tail>head){
head++;x=qx[head];y=qy[head];
for(int i=0;i<4;i++){
if((x+mx[i]>0&&x+mx[i]<=n&&y+my[i]>0&&y+my[i]<=m)——————————————>边界 &&((a[x+mx[i]][y+my[i]]!=1)&&(ans[x+mx[i]][y+my[i]]>ans[x][y]+1))){
其实可以不用这个。。 但这个是核心
qx[++tail]=x+mx[i];qy[tail]=y+my[i];
ans[x+mx[i]][y+my[i]]=ans[x][y]+1;
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)cout<<ans[i][j]<<" ";
cout<<endl;
}
return 0;
}
我们还有一种方法,但这种方法近乎于枚举(但是却AC了,玄学……):首先我们可以将每一排的最短路求出,即按如下所示:
0 0 0 1 0
--->3 2 1 0 1
由于我们这道题是只能向四周进行移动,我们现在已将每一排的最短路求出,即横向(左右向),所以我们现在就差竖向,所以我们可以再进行一次枚举,将竖向的最短路求出。如此,便得到答案,只需要输出答案即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 200
int m,n;
int map[N][N];
void L(int i,int j)
{
for(int l=1;l<=n;l++)
map[i][j]=min(map[i][j],abs(i-l)+map[l][j]);
}
void R(int i,int j)
{
for(int l=1;l<=m;l++)
map[i][l]=min(map[i][l],abs(l-j));
}
int main()
{
char s[N][N];
memset(map,0x7f,sizeof map);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]+1);
for(int j=1;j<=m;j++)
if(s[i][j]=='1') map[i][j]=0,R(i,j);
}
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(j==m) printf("%d\n",map[i][j]);
else printf("%d ",map[i][j]);
}
}*/
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
L(i,j);
if(j==m) printf("%d\n",map[i][j]);
else printf("%d ",map[i][j]);
}
}
}