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; }