hdu 4331 Image Recognition

http://acm.hdu.edu.cn/showproblem.php?pid=4331

我受不了了 这次比赛的题怎么回事 该超时的不超时  不该超的超了

比如说第四题 用二分 我感觉就应该让过的 他就是不让用哈希就过了 骑士那题结果dfs就过了

这个第一题吧  标程里面解析的 离散+树状数组那部分我没看懂 写了个暴力的 过了

应该是接近 n^3 的呀

唉 不说了 伤不起的题呀

由1组成的正方形 正方形的对角线一定在整个矩阵的某一斜线上  枚举这些斜线

每条斜线上为1的点打表  两两配对看是否能行 (这部分需要用到4个数组分别标记一个1点能上下左右延长的长度)

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<ctime>

#include<queue>

#include<cstring>

#include<set>

#include<cmath>

#include<algorithm>

#define LL long long

using namespace std;



const int N=1005;

int l[N][N],r[N][N],u[N][N],d[N][N];

int a[N][N];

struct node//某一斜线上1点的位置x 以及可以向左和右延伸的位置

{

    int x;

    int L,R;

}point[N];

int n;

int ans;

void findans(int I,int J)//对 从I J 为左上点开始的斜线进行求解

{

    int m=0;

    int s=0;

    for(int i=I,j=J;i<=n&&j<=n;++i,++j)

    {

        ++s;

        point[m].x=s;

        point[m].R=s+min(r[i][j],d[i][j])-1;

        point[m].L=s-min(l[i][j],u[i][j])+1;

        ++m;

    }

    for(int i=0;i<m;++i)

    {

        for(int j=i+1;j<m;++j)

        {

            if(point[i].R>=point[j].x&&point[j].L<=point[i].x)//枚举配对 这里不包含 一个1的情况

            ++ans;

        }

    }



}

int main()

{

   //freopen("data.txt","r",stdin);

   int T;

   scanf("%d",&T);

   for(int Case=1;Case<=T;++Case)

   {

       scanf("%d",&n);

       ans=0;

       memset(a,0,sizeof(a));

       memset(l,0,sizeof(l));

       memset(r,0,sizeof(r));

       memset(u,0,sizeof(u));

       memset(d,0,sizeof(d));

       for(int i=1;i<=n;++i)

       for(int j=1;j<=n;++j)

       {

           scanf("%d",&a[i][j]);

           ans+=a[i][j];//记录单个1的情况

       }

       //求各个方向1的延伸范围

       for(int i=1;i<=n;++i)

       for(int j=1;j<=n;++j)

       {

           if(a[i][j])

           {

               l[i][j]+=l[i][j-1]+1;

               u[i][j]+=u[i-1][j]+1;

           }else

           {

               l[i][j]=0;u[i][j]=0;

           }

       }

       for(int i=n;i>=1;--i)

       for(int j=n;j>=1;--j)

       {

           if(a[i][j])

           {

               d[i][j]=d[i+1][j]+1;

               r[i][j]=r[i][j+1]+1;

           }else

           {

               d[i][j]=0;r[i][j]=0;

           }

       }//枚举所有斜线起点

       for(int i=1;i<n;++i)

       findans(i,1);

       for(int j=2;j<n;++j)

       findans(1,j);

       printf("Case %d: %d\n",Case,ans);

   }

   return 0;

}

 

你可能感兴趣的:(image)