问题 J: Image Processing Project

这是一篇关于图像处理的项目,目的是为了进入伊朗领先的IT公司Cafebazaar。你需要在短时间内完成一个识别纸张数量的试点项目,这些纸张放在白色桌子上,形状为正方形,边界为黑色。输入包含像素的二维矩阵,任务是计算出纸张的数量。
摘要由CSDN通过智能技术生成

问题 J: Image Processing Project
时间限制: 1 Sec 内存限制: 128 MB
题目编号:10732

题目描述
You want to be recruited in Cafebazaar, a leading IT company in Iran, as part of an image processing project for detecting celestial bodies. To prove yourself, you should do a pilot project in a matter of hours for the project manager.
The project manager has put some paper sheets on a rectangular table whose color is white. All paper sheets are square and have the same size. Moreover, all paper sheets are white but their boundaries are black. Each side of all paper sheets is parallel to an edge of the table. You must write an image processing program to count the number of paper sheets by receiving a picture of the table taken from above.

输入
The first line of the input contains two positive integers r and c (3 ⩽ r, c ⩽ 200) denoting the number of rows and columns of the given picture, respectively. Precisely, the picture is an r × c table of pixels. The next r lines, each contains exactly c characters. Each character is +, -, or . representing a pixel of the picture. A dash pixel illustrates one unit of a horizontal side of a paper sheets. A plus pixel illustrates either one unit of a vertical side of a paper sheet or a corner of a paper sheet.
A dot pixel is a white pixel.
You can assume that in each row there exists at most one horizontal side. Similarly, in each column, there exists at most one vertical side. It is guaranteed that at least two corners of each paper sheet are visible. A corner is visible when along with the pixel corresponding to the corner, at least one immediate pixel from each of its incident edges is also present in the input. Moreover, It is guaranteed that there is at least a dash pixel in the input.

输出
Print the number of paper sheets in the output.

样例输入

10 13
+---+........
+...+........
+...+...+---+
+...+-+.+...+
+---+.+.+...+
..+..+--+...+
..+..+..+---+
..+--+...+...
.....+...+...
.....+---+...

样例输出
4

题目分析
每个矩形大小相等,矩形间可能存在遮挡但保证露出至少两个角,求此类矩形的个数
思路
矩形间相互遮挡,但一定存在没有被遮挡的矩形,因此可以先找到最大的合法矩形,此矩形必然是没有被遮挡的那个,然后对图像进行搜索与匹配,将所有搜过的点看做任意字符处理,如果一次遍历之后没有搜到新增的矩形,则可以停止遍历。

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=205;
char a[N][N];
    int n,m;
bool vis[N][N],v2[N][N];
int C=1,L=1;
void findsqr()
{
//函数功能:找到最大矩形并记录最大矩形横向纵向长度
    //memset(vis,0,sizeof vis);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            if(a[i][j]=='+')
            {
                int c,l;
                for(int k=j+1;k<m;k++)//找到此点为左上角的最大矩形
                    if(a[i][k]=='+')
                    {
                        c=k-j;
                        break;
                    }
                bool flag=true;
                for(int k=i+1;k<n&&flag;k++)
                    for(int p=0;p<c;p++)
                    {
                        if((p==0||p==c)&&(a[k][p+j]!='+')||((p>0&&p<c)&&a[k][p+j]!='.'))
                        {
                            l=k-i;
                            flag=false;
                            break;
                        }
                    }
                if((c+1)*(l+1)>(C+1)*(L+1))//判断矩形合法性
                {
                    bool flag=true;
                    for(int ii=0;ii<=l&&flag;ii++)
                        for(int jj=0;jj<=c&&flag;jj++)
                        {
                            if(a[i+ii][j+jj]!=((jj==0||jj==c)?'+':((ii==0||ii==l)?'-':'.')))
                            {
                                flag=false;
                                break;
                            }
                        }
                    if(flag==false) continue;
                    C=c;
                    L=l;
                }
 
            }
}
int countsqr(int t)
{
//函数功能:查找矩形个数
    int c=C,l=L;
    int temp=t;
    for(int i=0;i<=n-l;i++)
        for(int j=0;j<=m-c;j++)
            if(vis[i][j]||a[i][j]=='+')
            {
                int cnt=0;
                if(v2[i][j]) continue;//v2存储已经找到的矩形的左上角坐标,若v2已经存储过则跳过
                bool flag=true;
                for(int ii=0;ii<=l&&flag;ii++)//判断合法性
                    for(int jj=0;jj<=c&&flag;jj++)
                    {
                        if(!vis[i+ii][j+jj]&&((a[i+ii][j+jj])!=((jj==0||jj==c)?'+':((ii==0||ii==l)?'-':'.'))))
                        {
                            flag=false;
                            break;
                        }
                        if(!vis[i+ii][j+jj]&&(ii==0||ii==l)&&(jj==0||jj==c))
                            cnt++;
                    }
                if(cnt<2) continue;
                if(flag)//标记找到的矩形
                {
                    t++;
                    v2[i][j]=true;
                    for(int ii=0;ii<=l&&flag;ii++)
                        for(int jj=0;jj<=c&&flag;jj++)
                        {
                            vis[i+ii][j+jj]=true;
                        }
                }
            }
    return temp==t?t:countsqr(t);//如果t值发生改变则重新调用本函数再一次搜索,否则直接返回
}
int main()
{
    //bool f=true;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        for(int j=0;j<m;j++)
        //if(a[i][j]=='-') f=false;
    }
    findsqr();
    cout<<countsqr(0);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值