二维前缀和

网易的一道笔试题。

广场大小n*m,广场的某些坐标点上有障碍物,现在需要放置一个c*d大小的物品。问能否放得下?

输入:先输入测试组数t。接下来一行输入广场大小n,m和障碍物个数k。接下来k行每行两个数,代表障碍物的坐标。最后一行是两个数,代表要放的物品的尺寸c,d。

2

3 3 1

1 1

2 2

3 3 1

2 2

2 2

输出:判定结果

YES

NO

 

已知:

 1<=n,m<=1000;

1<=c<=n, 1<=d<=m

 

这道题用到二维前缀和。

所谓二维前缀和,可以用来快速计算大型矩阵的某二维方框内(确定范围内的)的所有数字之和。

详细解释参考链接:https://blog.csdn.net/qq_34990731/article/details/82807870

这道题需要先计算出n*m广场上的二维前缀和,然后枚举所有可能的位置,若出现了c*d大小范围内的和为0,则说明c*d内部没有一个障碍物,所以放得下。若枚举所有可能位置都未输出YES,则输出NO.

 

#include<bits/stdc++.h>
using namespace std;
//枚举货物放置的左上角,剩下的只需要检查某个矩形里面有没有障碍物。 
//把障碍物看成1,空格看成0,维护二维前缀和,就可以快速查询矩形和。
//如果矩形和是0则可以放置。
int n , m , k;
int a[1005][1005];
int c , d;
void solve(){
    scanf("%d%d%d",&n,&m,&k);
    memset(a , 0 , sizeof(a)) ;
    
    for(int i = 1;i <= k;i++) {
        int x , y;scanf("%d%d",&x,&y);
        a[x][y] = 1;
    }
    scanf("%d%d",&c,&d);
    for(int i = 1;i <= n;i++) {
        for(int j = 1;j <= m;j++) {
            a[i][j] += a[i-1][j] + a[i][j-1] - a[i-1][j-1] ;
        }
    }

    for(int i = 1;i <= n - c + 1 ; i ++) {
        for(int j = 1;j <= m - d + 1 ; j++) {
            int s = a[i+c-1][j+d-1] - a[i-1][j+d-1] - a[i+c-1][j-1] + a[i-1][j-1] ;
            if(!s) {
                puts("YES") ;return ;
            }
        }
    }
    puts("NO") ; return ;
}

int main(){
    int t ;scanf("%d",&t) ;
    while(t--) 
    	solve();
}

  

参考链接:https://www.nowcoder.com/discuss/216237

 

posted on 2019-08-05 15:36  逸阳  阅读(507)  评论(0编辑  收藏  举报

导航