买蛋糕(vijos1154)

算法:搜索

1.首先最优策略是1,2,4,8……至于为什么是这样我也不是太懂,有懂的童鞋希望能给我留个言。知道这个之后我们就可以直接试了,从而解决了第一个问题。
2.然后是这样一个结论,若现在已搜了K个数覆盖了1..s,那么剩下的数为s+1,2*(s+1),4*(s+1),这个原因同上。
3.然后就是搜索内部了,dfs(last,sum,now),其中last表示当前选的数的最后一个,sum表示当前和,now表示选了几个数。

对于剪枝,第一个剪枝比较好想,第二个剪枝有点难度,需要仔细的思考一下。
另外觉得这到题很像NOIP1999的那个邮票设计。
program VJ1154;

const
 maxn=1000;

var
 n,ans1,ans2:longint;
 a,s:array [0..maxn] of longint;

procedure dfs(last,sum,now:longint);
var
 i:longint;
begin
 if now>ans1 then exit;{剪枝1}
 if (now=ans1) and (sum>=n) then
  begin
   inc(ans2);
   exit;
  end;
 if (now<ans1) and (a[ans1-now]*(sum+1)-1>=n) then{剪枝2}
 for i:=last+1 to sum+1 do dfs(i,sum+i,now+1);{值存在于最后一个数+1到总和+1之间。}
end;

procedure minnest;
var
 i:longint;
begin
 a[0]:=1;
 s[0]:=1;
 ans1:=1;
 ans2:=0;
 for i:=1 to 12 do a[i]:=a[i-1] shl 1;
 for i:=1 to 12 do
  begin
   inc(s[i],a[i]+s[i-1]);
   if s[i]>=n then
    begin
     ans1:=i;
     break;
    end;
  end;
 inc(ans1); 
end;

begin
 assign(input,'VJ1154.in'); reset(input);
 assign(output,'VJ1154.out'); rewrite(output);

 readln(n);
 if n=1 then
  begin
   writeln(1,' ',1);
   close(input);
   close(output);
   halt;
  end;
 minnest;
 dfs(0,0,0);
 writeln(ans1,' ',ans2);

 close(input); close(output);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值