网易的一道笔试题。
广场大小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(); }