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;