CodeForces 1262E Arson In Berland Forest

Description
The Berland Forest can be represented as an infinite cell plane. Every cell contains a tree. That is, contained before the recent events.

A destructive fire raged through the Forest, and several trees were damaged by it. Precisely speaking, you have a n×m rectangle map which represents the damaged part of the Forest. The damaged trees were marked as “X” while the remaining ones were marked as “.”. You are sure that all burnt trees are shown on the map. All the trees outside the map are undamaged.

The firemen quickly extinguished the fire, and now they are investigating the cause of it. The main version is that there was an arson: at some moment of time (let’s consider it as 0) some trees were set on fire. At the beginning of minute 0, only the trees that were set on fire initially were burning. At the end of each minute, the fire spread from every burning tree to each of 8 neighboring trees. At the beginning of minute T, the fire was extinguished.

The firemen want to find the arsonists as quickly as possible. The problem is, they know neither the value of T (how long the fire has been raging) nor the coordinates of the trees that were initially set on fire. They want you to find the maximum value of T (to know how far could the arsonists escape) and a possible set of trees that could be initially set on fire.

Note that you’d like to maximize value T but the set of trees can be arbitrary.

Input

The first line contains two integer n and m (1≤n,m≤106, 1≤n⋅m≤106) — the sizes of the map.

Next n lines contain the map. The i-th line corresponds to the i-th row of the map and contains m-character string. The j-th character of the i-th string is “X” if the corresponding tree is burnt and “.” otherwise.

It’s guaranteed that the map contains at least one “X”.

Output

In the first line print the single integer T — the maximum time the Forest was on fire. In the next n lines print the certificate: the map (n×m rectangle) where the trees that were set on fire are marked as “X” and all other trees are marked as “.”.

Sample Input

3 6
XXXXXX
XXXXXX
XXXXXX

Sample Output

1

.X.XX.

思路:
最暴力的做法是把当前没燃烧的点加进队列里面,然后去搜索。
但是会T
所以改用前缀和
把从中间向四周燃烧,看作从左上想右方和下方燃烧两个格子。
记录要烧多久

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<algorithm>
#define max(a,b)   (a>b?a:b)
#define min(a,b)   (a<b?a:b)
#define swap(a,b)  (a=a+b,b=a-b,a=a-b)
#define memset(x,y) memset(x,y,sizeof(x))
#define ll long long
using namespace std;
int n,m;
int l=0,r=1e6;
int main()
	{
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	cin >> n >> m;
	vector<string> s(n);
	vector<vector<int>> arr(n,vector<int>(m));
	for(int i=0; i<n; i++) cin >> s[i];
	for(int i=0; i<n; i++)
		for(int j=0; j<m; j++)
			if(s[i][j]=='.') arr[i][j]=0;
			else if(i==0 || j==0) arr[i][j]=1;
			else arr[i][j]=min(arr[i-1][j-1],min(arr[i-1][j],arr[i][j-1]))+1;
	vector<vector<int>> b(n,vector<int>(m));
	while(r-l>1)
		{
		int mid=(l+r) >> 1;
		int x=2*mid+1;
		bool flag=true;
		for(int i=0; i<n; i++)
			for(int j=0; j<m; j++)
				if(arr[i][j]>=x) b[i][j]=x;
				else b[i][j]=0;
		for(int i=n-1; i>=0; i--)
			for(int j=m-1; j>=0; j--)
				{
				if(i>0) b[i-1][j]=max(b[i-1][j],b[i][j]-1);
				if(j>0) b[i][j-1]=max(b[i][j-1],b[i][j]-1);
				if(i>0 && j>0) b[i-1][j-1]=max(b[i-1][j-1],b[i][j]-1);
				}
		for(int i=0; i<n; i++)
			for(int j=0; j<m; j++)
				{
				if(arr[i][j]==0) continue;
				if(b[i][j]==0) flag=false;
				}
		if(flag) l=mid;
		else r=mid;
		}
	cout << l << endl;
	int x=2*l+1;
	vector<string> ans(n,string(m,'.'));
	for(int i=0; i<n; i++)
		for(int j=0; j<m; j++)
			if(arr[i][j]>=x) ans[i-l][j-l]='X';
	for(int i=0; i<n; i++)
		cout << ans[i] << endl;
	return 0;
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值