Codeforces Round #297 (Div. 2)D. Arthur and Walls 暴力搜索

本文详细阐述了如何解决 Codeforces Round #297 (Div. 2) D. Arthur and Walls 的问题,包括题目的背景介绍、关键概念解释、解题策略、代码实现和示例输入输出。重点在于通过爆搜、DFS、BFS 或者其他贪心策略来优化解法,确保在最小化墙壁移除数量的同时满足房间为矩形的要求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Codeforces Round #297 (Div. 2)D. Arthur and Walls

Time Limit: 2 Sec  Memory Limit: 512 MB
Submit: xxx  Solved: 2xx

题目连接

http://codeforces.com/contest/525/problem/D

Description

Finally it is a day when Arthur has enough money for buying an apartment. He found a great option close to the center of the city with a nice price.

Plan of the apartment found by Arthur looks like a rectangle n × m consisting of squares of size 1 × 1. Each of those squares contains either a wall (such square is denoted by a symbol "*" on the plan) or a free space (such square is denoted on the plan by a symbol ".").

Room in an apartment is a maximal connected area consisting of free squares. Squares are considered adjacent if they share a common side.

The old Arthur dream is to live in an apartment where all rooms are rectangles. He asks you to calculate minimum number of walls you need to remove in order to achieve this goal. After removing a wall from a square it becomes a free square. While removing the walls it is possible that some rooms unite into a single one.

Input

The first line of the input contains two integers n, m (1 ≤ n, m ≤ 2000) denoting the size of the Arthur apartments.

Following n lines each contain m symbols — the plan of the apartment.

If the cell is denoted by a symbol "*" then it contains a wall.

If the cell is denoted by a symbol "." then it this cell is free from walls and also this cell is contained in some of the rooms.

Output

Output n rows each consisting of m symbols that show how the Arthur apartment plan should look like after deleting the minimum number of walls in order to make each room (maximum connected area free from walls) be a rectangle.

If there are several possible answers, output any of them.


Sample Input

Input
5 5
.*.*.
*****
.*.*.
*****
.*.*.
 
Input
6 7
***.*.*
..*.*.*
*.*.*.*
*.*.*.*
..*...*
*******
 
Input
4 5
.....
.....
..***
..*..
 

Sample Output

Output
.*.*.
*****
.*.*.
*****
.*.*.
Output
***...*
..*...*
..*...*
..*...*
..*...*
*******
Output
.....
.....
.....
.....

HINT

 

 

题意:

给你一个n*m的田地,有一些*的地方是可以移除变成"。"的,然后问你移除最少的"*",使的每一个"。"的联通块都是矩形

题解:

爆搜! DFS、BFS、乱搞都能过,只要姿势优美!
我说一种解法,对于每一个"*",扫(i+1,j)(i,j+1)(i+1,j+1)这3个位置,假如都是"。"的话,那么"*"必然也应该变成"。",然后我们再回溯一下就好啦 ,这是一个O(n^2)的算法,不过这道题会卡常数
~\(≧▽≦)/~啦啦啦,讲完啦~

代码:

 

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 4001
#define mod 10007
#define eps 1e-9
//const int inf=0x7fffffff;   //无限大
const int inf=0x3f3f3f3f;
/*

*/
//**************************************************************************************
inline ll read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
string g[maxn];
int n,m;
void check(int x,int y)
{
    if(x<0||x>=n||y<0||y>=m)
        return;
    int cnt=0;
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            if(g[x+i][y+j]=='.')
                cnt++;
    if(cnt==3)
    {
        for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
                g[x+i][y+j]='.';
        for(int i=-1;i<2;i++)
            for(int j=-1;j<2;j++)
                check(x+i,y+j);
    }
    return;
}
int main()
{
    n=read(),m=read();
    for(int i=0;i<n;i++)
    {
            cin>>g[i];
    }
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            check(i,j);
        }
    }
    for(int i=0;i<n;i++)
    {
        cout<<g[i]<<endl;
    }
}

 

 

 

转载于:https://www.cnblogs.com/qscqesze/p/4371829.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值