zoukankan      html  css  js  c++  java
  • 城市统计【BFS】

    题目大意:

    中山市的地图是一个nn的矩阵,其中标号为1的表示商业区,标号为0的表示居民区。居民区i到商业区的距离指的是到距离它最近的商业区j的距离,而你将统计的是对于城市中的每一个区域k,以它为中心,所有满足max(|XkXm|,|YkYm|)r的区域m到商业区距离之和。


    思路:

    70分:
    O(n4)直接暴力求解即可。

    100分:

    BFS

    首先在读入的时候,若这个点是商业区,就先将它入队,之后跑一边BFS,求出每个居民区到商业区的距离(由于每个点只要访问1次,所以时间复杂度为O(n2)),之后用二维前缀和加速,输出每个位置的答案。总时间复杂度为O(tn2)


    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int dx[]={0,0,0,1,-1};
    const int dy[]={0,1,-1,0,0};
    int a[301][301],b[301][301],p[301][301],t,n,r,sum,head,tail,state[500001][3];
    
    int abs(int x)
    {
        if (x>0) return x;
        return -x;
    }
    
    int minn(int x)
    {
        return min(x,n);
    }
    
    int maxn(int x)
    {
        return max(x,0);
    }
    
    void bfs()
    {
        do
        {
            head++; 
            for (int i=1;i<=4;i++)  //向四个方向扩展
            {
                int xx=state[head][1]+dx[i];
                int yy=state[head][2]+dy[i];
                if (xx<0||xx>n||yy<0||yy>n||p[xx][yy]) continue;
                tail++;  //入队
                p[xx][yy]=1;
                state[tail][1]=xx;
                state[tail][2]=yy;
                b[xx][yy]=b[state[head][1]][state[head][2]]+1;
            }
        }
        while (head<tail);
        return;
    }
    
    int main()
    {
        scanf("%d",&t);
        while (t--)
        {
            memset(b,0,sizeof(b));
            memset(a,0,sizeof(a));
            memset(p,0,sizeof(p));
            scanf("%d%d",&n,&r);
            for (int i=1;i<=n;i++)
             for (int j=1;j<=n;j++)
             {
                scanf("%d",&a[i][j]);
                a[i][j]++;
                if (a[i][j]==2)  //商业区
                {
                    tail++;  //入队
                    state[tail][1]=i;
                    state[tail][2]=j;
                    p[i][j]=1;
                }
            } 
            bfs();
            for (int i=1;i<=n;i++)
             for (int j=1;j<=n;j++)
              b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];  //前缀和
            for (int i=1;i<=n;i++)
            {
                for (int j=1;j<=n;j++)
                 printf("%d ",b[minn(i+r)][minn(j+r)]-b[maxn(i-r-1)][minn(j+r)]-b[minn(i+r)][maxn(j-r-1)]+b[maxn(i-r-1)][maxn(j-r-1)]); 
                putchar(10);
            } 
            putchar(10);
        }
        return 0;
    }
  • 相关阅读:
    手游渠道分成的那些坑来等你跳
    [手游新项目历程]-43-sql关键字解决
    一些相似词的区别
    程序员之间的“笑料”
    程序员之间的“笑料”
    2014游戏圈员工跳槽必看
    2014游戏圈员工跳槽必看
    游戏应该怎么做-美术
    游戏应该怎么做-美术
    [手游新项目历程]-44-gdb
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998880.html
Copyright © 2011-2022 走看看