解题报告 keke 的房子
1. 题目
Keke的房子
Description
keke得到了一块n*m的土地,他灰常高兴,于是他想要盖个房子,keke的房子必须是正方形的。
但是,并不是土地的每个地方都能盖房子。地面上有一些地方不能盖一砖一瓦。
他当然希望将房子盖得大一些,房子越大就越舒服(有道理没有?)。
于是他又来恶心你了……
Input
输入文件第一行为两个整数n,m(1<=n,m<=1000),接下来n行,每行m个数字,用空格隔开。0表示该块土地不能盖房子,1表示该块土地完好。
Output
一个整数,为keke能盖出的最大正方形房子的边长
Sample Input
4 4
0 1 1 1
1 1 1 0
0 1 1 0
1 1 0 1
Sample Output
2
数据范围
对于30%的数据 n,m<=100
对于100%的数据 n,m<=1000
2. 题目实质
找一个指定区域内,不经过指定区域的最大的正方形的边长。
3. 算法
动态规划。
其实这个题还有一个更难的三角形版,也是需要从邻近的几个方向进行转移。
用 f[I,j] 存右下点为 I,j 的最大的正方形的边长,然后由画图 + 手模(手工模拟)得,最大正方形的边长应为与该格子左边相邻、上边相邻,或是与他的左上顶点相切的三个正方形中最小的那个的边长 + 1 。
然后,就实现就行了。
然后三角形版是需要从三个方向取最小的进行转移,然后走一遍正三角形,走一遍倒三角形。
4. 注意事项
这个题一定要动态规划,搜索最后两个点超时。
这个题的手模略。
5. 程序代码
艾 FHAI (Pascal)
var
f,a:array[0..1003,0..1003]of longint;
ans,tt,n,i,j,m:longint;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
begin
assign(input,'house.in');reset(input);
assign(output,'house.out');rewrite(output);
readln(n,m);
for i:=1to n do
begin
for j:=1 to m do
read(a[i,j]);
readln;
end;
for i:=1 to n do
for j:=1 to n do
if a[i,j]=1 then
begin
tt:=min(f[i,j-1],f[i-1,j]);
tt:=min(tt,f[i-1,j-1]);
f[i,j]:=tt+1;
if f[i,j]>ans then ans:=f[i,j];
end;
write(ans);
close(input);close(output);
end.