zoukankan      html  css  js  c++  java
  • 矩阵距离

    题目

    题目描述

    假设我们有矩阵,其元素值非零即1

    a11........a1m
    ...................
    ...................
    an1........anm

    定义aij与akl之间的距离为D(aij,akl)=abs(i-k)+abs(j-l)

    输入

    输入文件的第一行为两个整数,分别代表n和m。 
    接下来的n行,第i行的第 j个字符代表aij

    输出

    输出包含N行,每行M个用空格分开的数字,其中第i行第j个数字代表
    Min(D(aij,axy)) 其中1<=x<=N 1<=y<=M,且axy=1

    样例输入

    3 4 
    0001 
    0011 
    0110

    样例输出

    3 2 1 0 
    2 1 0 0 
    1 0 0 1

    数据范围

    1≤N,M≤1000

    分析

    一般人看到题后首先的想法一定是暴力。结果n^2m^2的时间复杂度轻松T掉,我也一样。于是有了广搜的思路(https://www.jianshu.com/p/bff70b786bb6)。若一个位置是1,则输出0。若是1,开始广搜,直到搜到离此点最近的1。然后求出D(aij,akl)=abs(i-k)+abs(j-l)。这保证值最小。代码如下。

    #include <bits/stdc++.h>
    using namespace std;
     
    int n,m;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    char a[1005][1005];
    queue<int> q1;
    queue<int> q2;
    inline int bfs(int x,int y)
    {
        q1.push(x);
        q2.push(y);
        while(!q1.empty()&&!q2.empty())
        {
            int qx=q1.front();
            int qy=q2.front();
            q1.pop();
            q2.pop();
            if(a[qx][qy]=='1') 
            {
                return abs(x-qx)+abs(y-qy);
            }
            for(int i=0;i<4;i++)
            {
                if(qx+dx[i]>n || qy+dy[i]>m || qy+dy[i]<=0 || qx+dx[i]<=0) continue;
                //if(x==3&&y==4) cout<<qx<<' '<<qy<<endl;
                q1.push(qx+dx[i]);
                q2.push(qy+dy[i]);
            }
             
        }
    }
     
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                if(a[i][j]=='1') cout<<0<<" ";
                else
                {
                    while(!q1.empty()&&!q2.empty())
                    {
                        q1.pop();
                        q2.pop();
                    }
                    cout<<bfs(i,j)<<" ";    
                }
            }
            cout<<endl;
        }
        return 0;
    }
    

    然后...............................................................................................就MLE了。

    给大家一组数据,可以试试。

    30 30

    000000000000000000000000000000
    000000000000000000000000000000
    000000000001000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000

    我的内心是崩溃的,要不是某李**拉着我我就把电脑砸了。

    正当我绝望之时,大佬(他的博客:https://www.cnblogs.com/chenjiaxuan/)告诉我了一个方法。

    这个方法与我的广搜相反。他没有广搜所有0,因为这样有几个0就要搜几次。他从1开始搜,搜所有的0并记录。于是时间复杂度就到了nm。代码如下

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,ans[1005][1005];
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    char a[1005][1005];
    queue<int> q1;
    queue<int> q2;
    inline void bfs()
    {
        while(!q1.empty()&&!q2.empty())	
        {
            int x=q1.front();
            int y=q2.front();
            q1.pop();
            q2.pop();
            for(int i=0;i<4;i++)
            {
            	int tx=x+dx[i],ty=y+dy[i];
                if(tx>n || ty>m || ty<=0 || tx<=0 || a[tx][ty]=='1' || ans[tx][ty]<=ans[x][y]+1) continue;
                ans[tx][ty]=ans[x][y]+1;
                q1.push(tx);
                q2.push(ty);
            }
        }
    }
     
    int main()
    {
    	memset(ans,999999,sizeof(ans));
        cin>>n>>m;
        for(int i=1;i<=n;i++)
    	    for(int j=1;j<=m;j++)
    		{
    			cin>>a[i][j];
    			if(a[i][j]=='1')
    			{
    				q1.push(i);
    				q2.push(j);
    				ans[i][j]=0;
    			}
    		}
    	bfs();
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++) cout<<ans[i][j]<<" ";
            cout<<endl;
        }
        return 0;
    }
    /*
    30 30
    000000000000000000000000000000
    000000000000000000000000000000
    000000000001000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    000000000000000000000000000000
    */
    

      

    我永远也忘不了那个AC的瞬间

  • 相关阅读:
    Vue:Axios异步通信,生命周期
    关于Hibernate多对多关联关系的更新问题。
    Hibernate多对多关联关系
    使用JQuery做一组复选框的功能。
    如何用jstl的select标签做二级联动下拉列表框??
    Ajax回退刷新页面问题的解决办法
    如何遍历一个JSON对象的属性值???
    一个关于JSON的异常,获取List对象失败的。。。
    阅读HandlerInterceptor接口源码的理解
    阅读HandlerInterceptor接口源码的理解
  • 原文地址:https://www.cnblogs.com/zxjhaha/p/11269742.html
Copyright © 2011-2022 走看看