「土」秘法地震

题目链接

题目描述:

帕秋莉掌握了一种土属性魔法 

这种魔法可以在一片k×k大小的一个正方形区域内产生地震

但是如果某片即将产生地震的区域内有建筑物,帕秋莉会停止施法

整个地图大小为n×m,其中一些地方有建筑

请问有多少种可能的情况,使得帕秋莉会停止施法

输入描述:

第一行三个数n, m, k,意义见描述
接下来一个n×m的01矩阵表示这篇区域的情况,1表示这个地方有建筑

输出描述:

输出一个数表示答案

输入

4 4 2
1000
0100
0000
0001

输出

5

题目不难理解,写的时候不会ToT

暴力所有的k * k的区间即可,重点是怎么求区间内有多少个建筑

因为这是一个二维的图,因此可以用二维前缀和来存储从端点 (1 , 1) 开始到(x, y)这个点的矩形有多少个建筑,转移方程很简单

dp[x][y] = dp[x - 1][y] + dp[x][y - 1] - dp[x - 1][y - 1];//一般形式
//本题目中应该是
dp[x][y] = dp[x - 1][y] + dp[x][y - 1] - dp[x - 1][y - 1] + mp[x][y];

很简单,画个图就可以直接得出

证明其实就是一个简单的容斥原理

dp[ i ][ j ]包含了 dp[ i - 1][ j ] 和 dp[ i ][j - 1],因此可以写成两部分相加的形式,而两部分相加后会多出dp[ i - 1][j - 1]这一部分,减去即可

求某一区间的和也很简单,本题中是这样的

bool check(int bx, int by){
	int ex = bx + k - 1;
	int ey = by + k - 1;
	return pre[ex][ey] - pre[bx - 1][ey] - pre[ex][by - 1] + pre[bx - 1][by - 1];
}

求出区间的左上和右下端点,然后计算和,计算方法也是容斥原理,图来

求 (x1, y1) 到 (x2, y2) 的和,先求出 (1, 1) 到 (x2, y2) 的和即 dp[ x2 ][ y2 ],分别减去两边多出的部分dp[ x2 - 1][y1] 和 dp[x1][y2 - 1],再加上多删除的部分即可

本题直接把二维前缀和应用到题目中即可

#include <bits/stdc++.h>
using namespace std;
const int N = 1100;
char mp[1100][1100];
int pre[N][N];
int n, m, k;
bool check(int bx, int by){
	int ex = bx + k - 1;
	int ey = by + k - 1;
	return pre[ex][ey] - pre[bx - 1][ey] - pre[ex][by - 1] + pre[bx - 1][by - 1];
}
int main()
{
	scanf("%d %d %d", &n, &m, &k);
	
	for (int i = 1; i <= n; i++){
		scanf("%s", mp[i] + 1);
	}
	memset(pre, 0, sizeof pre);
	for (int i = 1; i <= n; i++){//pre_work
		for (int j = 1; j <= m; j++){
			pre[i][j] = pre[i - 1][j] + pre[i][j - 1] - pre[i - 1][j - 1] + mp[i][j] - '0';
//			printf("%d ", pre[i][j]);
		}
//		puts("");
	}
	int res = 0;
	for (int i = 1; i <= n - k + 1; i++){
		for (int j = 1; j <= m - k + 1; j++){
			if(check(i, j)){
				++res;
			}
		}
	}
	printf("%d\n", res);
	return 0;
}
发布了143 篇原创文章 · 获赞 11 · 访问量 8213

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/103220331
今日推荐