【普组模拟赛】马农
题目:
在观看完战马检阅之后,来自大草原的两兄弟决心成为超级“马农”,专门饲养战马。
兄弟两回到草原,将可以养马的区域,分为 N*N 的单位面积的正方形, 并实地进行考察,归纳出了每个单位面积可以养马所获得的收益。接下来就要开始规划他们各自的马场了。
首先,两人的马场都必须是矩形区域。同时,为了方便两人互相照应,也为了防止马匹互相走散,规定两个马场的矩形区域相邻,且只有一个交点。最后,互不认输的两人希望两个马场的收益相当,这样才不会影响他们兄弟的感情。
现在,兄弟两找到你这位设计师,希望你给他们设计马场,问共有多少种设计方案。
比赛时绞尽脑汁都想不出来
其实正解就是暴力加所谓的“版本”优化
首先枚举交点
然后枚举其中一块,把答案数加到一个标记数组里
然后枚举另一块,加答案
单纯的这样去做会超时,因为数组太大,每次都初始化会爆时间
我们再加一个p[j]表示当前j这个位置的版本
首先我们定义一个v表示当前版本
每次枚举开始时v+1
然后在标记时和累加答案时看版本号对不对
对就照常做
不对就变版本号并且清零
这样就AC了
标程(请勿抄袭,后果很严重):
var map,sum:array[0..51,0..51]of longint;
bz:array[-7500000..7500000]of longint;
b:array[-7500000..7500000]of integer;
n,i,j,k,l,s,x,ans,now:longint;
begin
assign(input,'farmer.in');
assign(output,'farmer.out');
reset(input);
rewrite(output);
readln(n);
for i:=1 to n do
for j:=1 to n do
begin
read(map[i,j]);
sum[i,j]:=sum[i-1,j]+sum[i,j-1]-sum[i-1,j-1]+map[i,j];
end;
x:=0;
now:=0;
for i:=1 to n do
for j:=1 to n do
begin
inc(now);
for k:=1 to i do
for l:=1 to j do
begin
if b[sum[i,j]-sum[k-1,j]-sum[i,l-1]+sum[k-1,l-1]]<>now then
begin
b[sum[i,j]-sum[k-1,j]-sum[i,l-1]+sum[k-1,l-1]]:=now;
bz[sum[i,j]-sum[k-1,j]-sum[i,l-1]+sum[k-1,l-1]]:=0;
end;
inc(bz[sum[i,j]-sum[k-1,j]-sum[i,l-1]+sum[k-1,l-1]]);
end;
for k:=i+1 to n do
for l:=j+1 to n do
if b[sum[k,l]-sum[i,l]-sum[k,j]+sum[i,j]]=now then
ans:=ans+bz[sum[k,l]-sum[i,l]-sum[k,j]+sum[i,j]];
inc(now);
for k:=1 to i do
for l:=j to n do
begin
if b[sum[i,l]-sum[k-1,l]-sum[i,j-1]+sum[k-1,j-1]]<>now then
begin
b[sum[i,l]-sum[k-1,l]-sum[i,j-1]+sum[k-1,j-1]]:=now;
bz[sum[i,l]-sum[k-1,l]-sum[i,j-1]+sum[k-1,j-1]]:=0;
end;
inc(bz[sum[i,l]-sum[k-1,l]-sum[i,j-1]+sum[k-1,j-1]]);
end;
for k:=i+1 to n do
for l:=1 to j-1 do
if b[sum[k,j-1]-sum[i,j-1]-sum[k,l-1]+sum[i,l-1]]=now then
ans:=ans+bz[sum[k,j-1]-sum[i,j-1]-sum[k,l-1]+sum[i,l-1]];
end;
writeln(ans);
close(input);
close(output);
end.