【思维】Codeforces 1059B - Forgery

版权声明:本博客主要用于记录思考过程,方便复习,欢迎留言交流讨论~ https://blog.csdn.net/Floraqiu/article/details/82949479

【思维】Codeforces 1059B - Forgery

Student Andrey has been skipping physical education lessons for the whole term, and now he must somehow get a passing grade on this subject. Obviously, it is impossible to do this by legal means, but Andrey doesn’t give up. Having obtained an empty certificate from a local hospital, he is going to use his knowledge of local doctor’s handwriting to make a counterfeit certificate of illness. However, after writing most of the certificate, Andrey suddenly discovered that doctor’s signature is impossible to forge. Or is it?

For simplicity, the signature is represented as an n×m grid, where every cell is either filled with ink or empty. Andrey’s pen can fill a 3 × 3
square without its central cell if it is completely contained inside the grid, as shown below.
xxx
x.x
xxx
Determine whether is it possible to forge the signature on an empty n × m grid.

Input
The first line of input contains two integers n and m (3 ≤ n , m ≤ 1000 ).

Then n lines follow, each contains m characters. Each of the characters is either ‘.’ , representing an empty cell, or ‘#’, representing an ink filled cell.

Output
If Andrey can forge the signature, output “YES”. Otherwise output “NO”.

You can print each letter in any case (upper or lower).

Examples

input
3 3
###
#.#
###
output
YES

input
3 3
###
###
###
output
NO

input
4 3
###
###
###
###
output
YES

input
5 7
.......
.#####.
.#.#.#.
.#####.
.......
output
YES

扫描二维码关注公众号,回复: 5001654 查看本文章

Note
In the first sample Andrey can paint the border of the square with the center in (2,2).

In the second sample the signature is impossible to forge.

In the third sample Andrey can paint the borders of the squares with the centers in (2,2) and (3,2):

  1. we have a clear paper:
    ...
    ...
    ...
    ...
  2. use the pen with center at (2,2).
    ###
    #.#
    ###
    ...
  3. use the pen with center at (3,2).
    ###
    ###
    ###
    ###

In the fourth sample Andrey can paint the borders of the squares with the centers in (3,3) and (3,5).

题意:

xxx
x.x
xxx
有一个印章,形状如上(X表示有墨水,.表示空),给你一个图形,问是否能够用这个章盖出来。

思路:

  1. 我们发现要使某一个格子盖上墨水,其必须有一个中心,也就是说这个有墨水的格子的四周8格中有一个作为它的中心,它才有可能被盖上墨水。因此对于任意一个有墨水的格子,它周围的8个格子中,至少存在一个可以作为中心的格子。
  2. 那么什么样的格子可以作为中心呢?
    (1) 观察印章的形状,它的中心为空,四周8个格子有墨水,因此对于任何一个空格子,其四周8个格子不能够作为中心,一旦其作为中心,这个空格子就会被染色。
    (2)四周的边界不能够作为中心,因为如果它们作为中心,那么盖章的时候就会盖到外面去,这是不允许的。
    以上我们找到了不能够作为中心的格子(称之为禁戒细胞),那么剩下的就是可以作为中心的格子。
  3. 综上,我们可以先对所有的格子进行处理,找出所有禁戒细胞,然后再对所有墨水格进行检测,其周围8个格子是否至少有一个非禁戒细胞。如果满足上诉条件,则说明可以盖出这个的章,输出“YES”,否则输出“NO”。

代码:

(官方题解代码:)

#include<bits/stdc++.h>

using namespace std;

const int maxn = (int)1e3 + 3;

int n, m;
char a[maxn][maxn];
bool can[maxn][maxn];
vector<int> must_have[maxn][maxn];

inline bool inside(int x, int y){
	return x >= 0 && y >= 0 && x < n && y < m;
}

int main(){
	scanf("%d%d", &n, &m);
	for(int i = 0; i < n; i++)
		for(int j = 0; j < m; j++)
			can[i][j] = true;
	for(int i = 0; i < n; i++)
		for(int j = 0; j < m; j++){
			do{
				a[i][j] = getc(stdin);
			}while(a[i][j] != '.' && a[i][j] != '#');
			for(int dx = -1; dx <= 1; dx++)
				for(int dy = -1; dy <= 1; dy++){
					if(abs(dx) + abs(dy) == 0 || !inside(i + dx, j + dy))continue;
					if(a[i][j] == '.')can[i + dx][j + dy] = false;
					else if (i + dx != 0 && j + dy != 0 && i + dx != n - 1 && j + dy != m - 1)must_have[i][j].push_back((i + dx) * m + j + dy);
				}
		}
	for(int i = 0; i < n; i++)
		for(int j = 0; j < m; j++){
			bool good = false;
			if(a[i][j] == '.')continue;
			for(int cand : must_have[i][j]){
				int x = cand/m, y = cand%m;
				good |= can[x][y];
			}
			if(!good){printf("NO"); return 0;}
		}
	printf("YES");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Floraqiu/article/details/82949479