1387 农场
题目地址:http://acm.uestc.edu.cn/problem.php?pid=1367&cid=98
恩 水题。确实水题。但俺没过。
因为数据比较大 简单枚举就爆掉了 要用类似dp的方法 定义dp[i][j]表示
在求 (i-A+1, j-B+1) - (i,j) 这块 A*B 区域内有无被占用的点时,只需做一次加减运算。 种有植物的点的点数为 (dp[i][j]+ dp[i-A][j-B]) - (dp[i-A][j]+ dp[i][j-B])
按照这一思路用两重循环就能得到答案 要注意的只有 当A==B的时候ans要除2;
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h>
#include <string.h>
int badfrm[1002][1002];
int farm[1002][1002];
int main()
{
int T, N, r, c, p, q, i, j, x, y, A, B, k, cas = 1;
scanf("%d", &T);
while (T--) {
memset(badfrm, 0, sizeof(badfrm));
memset(farm, 0, sizeof(farm));
scanf("%d%d%d%d", &r, &c, &p, &q);
for (i = 0; i < p; i++) {
scanf("%d%d", &x, &y);
badfrm[x][y] = 1;
}
for (i = 1; i <= r; i++) {
farm[1][i] = farm[1][i - 1] + badfrm[1][i];
}
for (i = 1; i <= c; i++) {
farm[i][1] = farm[i - 1][1] + badfrm[i][1];
}
for (i = 2; i <= r; i++) {
for (j = 2; j <= c; j++) {
farm[j][i] = farm[j][i - 1] + farm[j - 1][i] - farm[j - 1][i - 1] + badfrm[j][i];
}
}
printf("Case #%d:\n", cas++);
for (k = 0; k < q; k++) {
int ans = 0, isbad = 0;
scanf("%d%d", &A, &B);
for (i = 0; i <= r - A; i++) {
for (j = 0; j <= c - B; j++) {
isbad = farm[j][i] + farm[j + B][i + A] - farm[j + B][i] - farm[j][i + A];
if (isbad == 0)
ans++;
}
}
for (i = 0; i <= r - B; i++) {
for (j = 0; j <= c - A; j++) {
isbad = farm[j][i] + farm[j + A][i + B] - farm[j + A][i] - farm[j][i + B];
if (isbad == 0)
ans++;
}
}
if (A == B)
ans /= 2;
printf("%d\n", ans);
}
}
return 0;
}