2017.8.15 提高B组模拟总结

t1

Alice要搭建平台,平台不能漂在空气中,必须要有两根柱子支撑,具体地说,每个平台的两端必须由一根柱子支撑,柱子的另一端在地板或另一个平台上。
  给你平台的放置位置(如下左图所示),每个平台的位置由它的高度(离地面的垂直距离)和水平方向两个端点的坐标决定,每根柱子必须安放在离端点0.5个单位的位置,如下右图所示。
编程计算所需柱子总长是多少。
 第一行包含整数N,1<=N<=100,表示平台的数量。
  接下来N行,每行三个数Y,X1和X2用来描述每个平台的位置,Y表示高度,X1,X2表示两个端点的X坐标,三个数都是正整数,并且小于等于10000,同时满足X2>X1+1(也就是说平台的长度至少为2)。
  输入保证平台不会重叠。


好吧,小水题一道,但是。。。。我打炸了。。。这件事告诉我,下次要打对拍。。
你拍我拍大家拍,大家拍才是真的A,不拍必死。。。
很简单,排序后直接枚举即可

procedure so(i:longint);
var
        j:longint;
begin
        for j:=i-1 downto 1do
        begin
                if (y[j]>x[i])and(x[i]>=x[j])and(bz[i,1]=false) then
                begin
                        bz[i,1]:=true;
                        ans:=ans-h[j];
                end;
                if (y[j]>=y[i])and(x[j]<y[i])and(bz[i,2]=false) then
                begin
                        bz[i,2]:=true;
                        ans:=ans-h[j];
                end;
        end;
end;

bz判断左右支柱是否被节省过,没被节省过则通过枚举找出它下方的第一个平台来节省自己的支柱。


t2

  游戏在一行N个方块中进行,编号为1到N,一开始Alice在方块1中,第一次只能跳到方块2中,接下来每一次跳跃必须满足以下两个限制:
  (1) 如果是向前跳(即跳到比现在编号大的方块),跳跃距离必须比上一次要大1;
  (2) 如果是向后跳(即跳到比现在编号小的方块),跳跃距离必须跟上一次一样。
  例如,第一次跳跃后,Alice可以跳回1也可以跳到4。
  每进入一个方块,Alice必须支付一定的费用,Alice的目标花最少的钱从方块1跳到方块N。编程计算最小的花费。
  第一行包含一个整数N(2<=N<=1000),表示方块的个数。
  接下来N行,每行包含一个不超过500的正整数表示进入该方块的费用。  


看上去很复杂,实际上你只要把普通的dp多跑几遍就可以过了,自己去卡时间
当然你也可以用贪心的方法,但是博主比较懒,所以并没有去想,代码我也不贴了,自行解决吧。
注意dp是双向的,但是多跑几遍后就没有后效性了。


t3

  Alice在餐馆里当服务员,今天是她生日,她请求厨师帮她准备生日晚餐,晚餐由N种原料做成,每道菜所需每种原料的数量是一样的。
  厨房里有一些原料,但不够,Alice还需要从旁边的超市中购买一些回来。超市里什么原料都有,每种原料都分大包装和小包装。Alice有M元钱,她想利用这M元钱购买原料使得能做出最多的菜。
 第一行包含两个整数N和M(1<=N<=100,1<=M<=100000),接下来N行,每行包含6个正整数,用来描述这种原料的信息,具体如下:
  (1) X:10<=X<=100,表示一道菜中必须含有这种原料的数量;
  (2) Y:1<=Y<=100,表示这种原料厨房已有的数量;
  (3) Sm:1<=Sm<=100,表示超市里小包装中含有这种原料数量;
  (4) Pm:10<=Pm<=100,表示小包装的价格;
  (5) Sv:1<=Sv<=100,表示超市里大包装中含有这种原料数量;   
(6) Pv:10<=Pv<=100,表示大包装的价格;


这又是一道猥猥琐琐的二分题,博主本人作为一名蒟蒻,是最讨厌二分题的,因为比赛的时候根本就想不到。

二分一个mid,然后再用贪心的方法算出要做出mid道菜的话,每一种菜还要多少钱才能满足条件,然后如果代价大于m则将mid缩小,否则反之,最后即可得到最大的符合条件的mid。

        l:=0;
        r:=m;
        now:=(l+r) div 2;
        while l<r do
        begin
                ans:=0;
                for i:=1 to n do
                        need[i]:=x[i]*now-y[i];
                for i:=1 to n do
                begin
                        ans1:=maxlongint;
                        if need[i] mod sv[i]=0 then s:=0
                        else s:=1;

                        for j:=0 to need[i] div sv[i]+s do
                        begin
                                if (need[i]-j*sv[i]) mod sm[i]=0 then ss:=0
                                else ss:=1;
                                k:=(need[i]-j*sv[i]) div sm[i]+ss;
                                if need[i]-j*sv[i]<=0 then k:=0;
                                if ans1>j*pv[i]+k*pm[i] then
                                        ans1:=j*pv[i]+k*pm[i];
                        end;
                        ans:=ans+ans1;
                end;
                if ans<=m then
                begin
                        l:=now+1;
                        now:=(l+r) div 2;
                end
                else
                begin
                        r:=now;
                        now:=(l+r) div 2;
                end;
        end;

注意最后当l=r退出后还要再算一次判断当前mid是否符合条件,如果不符就将mid减1再输出。


t4

当Alice在浏览数学书时,看到一个等式A=S,奇怪的是A和S并不相等。Alice发现可以通过在A中添加加号“+”从而使得等式成立。
编程计算最少需要插入多少加号使得等式成立。允许每个数有多个前导0。
输入第一行包含一个等式形式为A=S。
A和S都是没有前导0的正整数,并保证不相同。
A最多有1000位。
S<=5000。
输入保证有解。


我承认,作为一名蒟蒻,看到这题的时候我是一脸懵逼的,果断放弃了。。。。
数位dp,设f[i,j]表示到第i位,式子A的值为j时要用的最少加号数,最后输出f[length(a),s]即可

        fillchar(f,sizeof(f),127);
        f[0,0]:=0;
        for i:=1 to n do
          for j:=0 to m do
          begin
                p:=0;
                q:=1;
                for k:=i downto 1 do
                begin
                        p:=p+z[k]*q;
                        q:=q*10;
                        if (q>10000)then break;
                        if z[i]=0 then f[i,j]:=min(f[i,j],f[i-1,j]);
                        if (j>=p) then f[i,j]:=min(f[i,j],f[k-1,j-p]+1)
                        else break;
                end;
          end;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值