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;
}
原文地址:https://www.cnblogs.com/liulangye/p/2621100.html