5.18特长生模拟题 Chocolate

题目

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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值