01距离 解题报告

来源:互联网 发布:fifaol3数据库 编辑:程序博客网 时间:2024/06/06 20:04

【输入样例】

3 4

0001

0011

0110

【输出样例】

3 2 1 0

2 1 0 0

1 0 0 1

【数据范围及提示】

对于30%的数据,n*m<=10000;

对于100%的数据,n*m<=182^2.


【解题思路】

之前的思路不太对啊。。每找到一个0就广搜一遍。。明显超时(⊙o⊙)…

然而反向思维就是正解了。。。

由题目描述可以知道dis[i,j]其实就是点(i,j)到离他最近的那个为1的点的最小步数,这一类问题就是经典的广搜问题;

首先寻找值为1的点,把他们如队列;

然后从队列首开始扫,每次扩展队列中元素周围的四个点,如果是0就入队列,步数是头指针+1;

这样就很容易求出答案;

queue[i][0]为队列中第i个元素的横坐标;

queue[i][1]为队列中第i个元素的纵坐标;

queue[i][2]为队列中第i个元素的dis,也就是最小步数;


【代码】

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;int sx[4]={1,-1,0,0};int sy[4]={0,0,1,-1};int queue[40000][3];int n,m,head,tail,i,j,a[2000][2000],dis[2000][2000],x,y;char ss[2000];int main(){freopen("dis.in","r",stdin);freopen("dis.out","w",stdout);scanf("%d%d",&n,&m);head=0;tail=0;for (i=1;i<=n;++i){cin>>ss;for (j=1;j<=m;++j){a[i][j]=ss[j-1]-48;if (a[i][j]==1)//寻找所有的1,入队列{tail++;queue[tail][0]=i;queue[tail][1]=j;queue[tail][2]=0;}}}while (head<tail){head++;for (i=0;i<4;++i)//向头指针的四个方向扩展{x=queue[head][0]+sx[i];y=queue[head][1]+sy[i];if (x>0&&y>0&&x<=n&&y<=m&&a[x][y]==0)//判断是否越界以及是否为0{a[x][y]=1;tail++;//入队列queue[tail][0]=x;queue[tail][1]=y;queue[tail][2]=queue[head][2]+1;//步数+1dis[x][y]=queue[tail][2];//dis的值就等于最小步数}}}for (i=1;i<=n;++i){for (j=1;j<=m;++j)  printf("%d ",dis[i][j]);printf("\n");}return 0;}
【心得】

有的时候需要逆向思维。。。就差那么一点点。、

0 0