• 【CF525D】Arthur and Walls


    题目

    题目链接:https://codeforces.com/problemset/problem/525/D
    给出一个 (n imes m) 的矩阵,里面有 *. 两种符号,要求把最少的 * 变成 .,使得 . 的联通块构成一个矩形。求最少需要变几个 *

    思路

    如果一个由 . 构成的连通块是一个矩形,那么这个连通块内任意的一个子矩形都是由 . 构成的
    所以说我们只需要判断每一个 (2 imes 2) 的子矩形,如果这个子矩形中有 (3).,那么就把剩下的一个 * 变成 .
    拓扑排序即可。
    时间复杂度 (O(nm))

    代码

    #include <bits/stdc++.h>
    #define mp make_pair
    using namespace std;
    
    const int N=2010;
    const int dx[9]={0,-1,1,-1,1,-1,1,0,0},dy[9]={0,-1,1,1,-1,0,0,-1,1};
    int n,m;
    char ch[N][N];
    queue<pair<int,int> > q;
    
    void check(int i,int j)
    {
    	bool flag=0;
    	if (ch[i-1][j]=='.' && ch[i][j-1]=='.' && ch[i-1][j-1]=='.') flag=1;
    	if (ch[i-1][j]=='.' && ch[i][j+1]=='.' && ch[i-1][j+1]=='.') flag=1;
    	if (ch[i+1][j]=='.' && ch[i][j-1]=='.' && ch[i+1][j-1]=='.') flag=1;
    	if (ch[i+1][j]=='.' && ch[i][j+1]=='.' && ch[i+1][j+1]=='.') flag=1;
    	if (flag) q.push(mp(i,j)),ch[i][j]='.';
    }
    
    void topsort()
    {
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			if (ch[i][j]=='*') check(i,j);
    	while (q.size())
    	{
    		int x=q.front().first,y=q.front().second;
    		q.pop();
    		for (int k=1;k<=8;k++)
    		{
    			int i=x+dx[k],j=y+dy[k];
    			if (ch[i][j]=='*') check(i,j);
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		for (int j=1;j<=m;j++)
    			while (ch[i][j]=getchar())
    				if (ch[i][j]=='.' || ch[i][j]=='*') break;
    	topsort();
    	for (int i=1;i<=n;i++)
    	{
    		for (int j=1;j<=m;j++)
    			putchar(ch[i][j]);
    		putchar(10);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    排序算法合集(冒泡,选择,插入,堆排,快排)
    codeforces 632+ E. Thief in a Shop
    nyoj-一笔画问题-欧拉图+联通判定
    hdu-1179-二分图最大匹配
    hdu-2063-二分图最大匹配
    (转)二分图的最大匹配、完美匹配和匈牙利算法
    hdu-2444-二分图判定+最大分配
    C
    E
    C
  • 原文地址:https://www.cnblogs.com/stoorz/p/13843284.html
Copyright © 2020-2023  润新知