题目
Charlie 有一块巧克力。
这块巧克力是矩形的,有n 行m 列一共n m 个大小相同的小块,每一小
块都有一个美味值ai;j。
Charlie 有k 个朋友,他希望把巧克力分给这些朋友。
Charlie 按如下方法分配巧克力:做k��1 次分割,每次拿出一块巧克力,将它
沿水平或竖直方向分成两块矩形的巧克力。分割完成后一共有k 块巧克力,Charlie
会把这k 块巧克力一一分给他的朋友们。
一块巧克力的美味值定义为它的所有小块的美味值之和。Charlie 想知道是否
存在一种可行的方案,使每个朋友获得的巧克力的美味值相等。
题解
深搜+剪枝
巧克力总美味值和不能整除k则直接输出NO
设平均每个人得到的美味值为d
一块矩形巧克力的美味值和用一个二维前缀和数组表示
每次转移左上角坐标和右上角坐标
当前矩形大于d则继续转移,小于d则退出,等于d则这个矩形合法
若一个矩形可以成功的分成若干个美味值为d的则该矩形合法
最后要记忆化,f[x1,y1,x2,y2]记录状态
时间复杂度O(n2m2(n+m))
代码
var
t,n,m,k,l,i,j,c,b:longint;
a:array[0..24,0..24]of longint;
f:array[1..24,1..24,1..24,1..24]of longint;
function s(x1,y1,x2,y2:longint):longint;
begin
exit(a[x2,y2]-a[x2,y1-1]-a[x1-1,y2]+a[x1-1,y1-1]);
end;
function dfs(x1,y1,x2,y2:longint):boolean;
var
i:longint;
begin
if f[x1,y1,x2,y2]=2 then exit(false);
if s(x1,y1,x2,y2)=b then begin f[x1,y1,x2,y2]:=1;exit(true);end;
if s(x1,y1,x2,y2)<b then begin f[x1,y1,x2,y2]:=2;exit(false);end;
for i:=x1 to x2-1 do
if (dfs(x1,y1,i,y2)or(f[x1,y1,i,y2]=1))
and(dfs(i+1,y1,x2,y2)or(f[i+1,y1,x2,y2]=1)) then
begin f[x1,y1,x2,y2]:=1;exit(true);end;
for i:=y1 to y2-1 do
if (dfs(x1,y1,x2,i)or(f[x1,y1,x2,i]=1))
and(dfs(x1,i+1,x2,y2)or(f[x1,i+1,x2,y2]=1)) then
begin f[x1,y1,x2,y2]:=1;exit(true);end;
f[x1,y1,x2,y2]:=2;
exit(false);
end;
begin
assign(input,'chocolate.in');
assign(output,'chocolate.out');
reset(input);rewrite(output);
readln(t);
for l:=1 to t do
begin
readln(n,m,k);
fillchar(f,sizeof(f),0);
fillchar(a,sizeof(a),0);
c:=0;
for i:=1 to n do
for j:=1 to m do
begin
read(a[i,j]);
c:=c+a[i,j];
a[i,j]:=a[i,j]+a[i-1,j]+a[i,j-1]-a[i-1,j-1];
end;
b:=c div k;
if c mod k<>0 then writeln('NO') else
if dfs(1,1,n,m) then writeln('YES') else writeln('NO');
end;
close(input);close(output);
end.