题目描述
在前面的游戏中,由于moreD每次都用最优策略赢了他的宠物CD,CD现在很郁闷,于是他一个人在地板上画画东西了。别人都是说,“画个圈圈诅咒你”,但是CD很有特点,他喜欢“画个框框诅咒你…”。
现在我们把CD画的东西记录到一个N×N方阵上了,1表示CD画过的地方,0表示空白,请问CD最多可能画了多少不重复个方框呢?
方框就是所有以1为边的正方形,最小的方框是一个1,CD画方框的时候,是完全可能把两个不一样的方框的某些边重复画到同一个位置上的。参见样例。
输入格式
第一行输入一个整数N,1<=N<=1000。
接下来N行,每行N个数,1或者0。
输出格式
输出一个整数,表示CD最多可能画了多少不重复个方框。
样例
样例输入
3
1 1 0
1 1 0
0 0 0
样例输出
5
数据范围与提示
【样例输入2】
3
1 1 1
1 0 1
1 1 1
【样例输出2】
9
【数据描述】
对于30%的数据N<=100。
对于50%的数据N<=500。
对于100%的数据N<=1000。
来源
20121007
题
解
:
题解:
题解:
首
先
暴
力
统
计
,
但
首先暴力统计,但
首先暴力统计,但N^3
太
大
。
太大。
太大。
所
以
考
虑
对
每
个
点
分
成
两
部
分
算
所以考虑对每个点分成两部分算
所以考虑对每个点分成两部分算
一
部
分
是
实
心
正
方
形
一部分是实心正方形
一部分是实心正方形
设
f
[
i
]
[
j
]
表
示
以
(
i
,
j
)
为
右
上
角
的
实
心
正
方
形
的
最
大
边
长
设f[i][j]表示以(i,j)为右上角的实心正方形的最大边长
设f[i][j]表示以(i,j)为右上角的实心正方形的最大边长
同
时
可
以
维
护
行
连
续
长
度
l
和
列
连
续
长
度
r
同时可以维护行连续长度l和列连续长度r
同时可以维护行连续长度l和列连续长度r
f
[
i
]
[
j
]
=
m
i
n
(
f
[
i
−
1
]
[
j
−
1
]
+
1
,
m
i
n
(
l
,
r
)
)
;
f[i][j]=min(f[i-1][j-1]+1,min(l,r));
f[i][j]=min(f[i−1][j−1]+1,min(l,r));
这
时
可
以
优
化
时
间
a
n
s
+
=
f
[
i
]
[
j
]
这时可以优化时间ans+=f[i][j]
这时可以优化时间ans+=f[i][j]
另
一
部
分
暴
力
统
计
另一部分暴力统计
另一部分暴力统计
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define N 1005
using namespace std;
int n,m[N][N],sumh[N][N],suml[N][N],sum[N][N],f[N][N],l[N],r[N];
int ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
scanf("%d",&m[i][j]);
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
sumh[i][j]=sumh[i][j-1]+m[i][j];
suml[i][j]=suml[i-1][j]+m[i][j];
//sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+m[i][j];
}
}
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
if(m[i][j])l[i]++,r[j]++;
else l[i]=0,r[j]=0;
if(f[i-1][j-1]+1>=min(l[i],r[j])){f[i][j]=min(l[i],r[j]);ans+=min(l[i],r[j]);continue;}
f[i][j]=f[i-1][j-1]+1;ans+=f[i][j];
//if(i==3&&j==3)cout<<f[i][j]<<endl;
for(int k=f[i][j]+1;k<=min(l[i],r[j]);++k){
int x=i-k+1,y=j-k+1;
//if(sumh[i][y]-sumh[i][j-1]!=k||suml[x][j]-suml[i-1][j]!=k)break;
if(sumh[x][j]-sumh[x][y-1]==k&&suml[i][y]-suml[x-1][y]==k)ans++;
/*if(i==3&&j==3){
cout<<k<<endl;
cout<<sumh[x][y]-sumh[x][j-1]<<" "<<suml[x][y]-suml[i-1][y]<<endl;
}*/
}
}
}
printf("%d\n",ans);
return 0;
}
/*
3
1 1 1
1 0 1
1 1 1
*/