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的瞬间

  • 相关阅读:
    288 Node.js模块化开发:js开发弊端,模块的概念,模块成员导出的2种方式及其区别,模块成员导入
    287 Node.js快速入门:Node.js 的组成,Node.js基础语法,Node.js全局对象global
    286 Node开发概述,Node运行环境搭建以及安装失败解决办法
    285 H5 Web Workers
    使用nvm安装nodejs
    函数式 UI:Web开发终于摆脱了框架的束缚
    Vue渲染函数
    微信小程序使用canvas实现生成海报图的功能
    Vue中插槽指令
    Vue之nextTick原理
  • 原文地址:https://www.cnblogs.com/zxjhaha/p/11269742.html
Copyright © 2011-2022 走看看