您的位置:首页 > 其它

NOIP 2011 提高组 选择客栈(vijos 1737)(方法:队列,数学)

2013-10-17 14:58 615 查看
附: 题目链接 vijos 1737 地址:https://www.vijos.org/p/1737

srO 来自嘘嘘大神@oxxxo 的神级O(n) 打法 Orz

srO 而且该打法不长,可丧心病狂的压到10行 Orz

[b]该题嘘嘘大神@oxxxo 的思路:[/b]

对于每个客栈(最低消费 v,格调 c),在、之前的、出现的所有、跟、该客栈、同格调的客栈、符合旅客要求、的前提是 :

在、这两客栈间存在一家最低消费<= p 的客栈,记 f 为离当前决策客栈、最近的、最低消费 <= p的、客栈编号,则、当前

决策点之前、能与该点、组成符合要求的、客栈即为:前 f 家客栈中、与该决策客栈同格调的客栈。

所以思路就很明显了:开一个 can[0..50] 的数组记录前 f 家客栈中格调为 x的数量,记为 can[x] ;则、当前决策点能增加

的方案数为 can[x] ,每次只要把 answer 的值加上 can[决策点]的值即可。

按这个思路,最后要完成的步骤就是: 对 can 这个数组的维护,按嘘嘘大神的方法,再开一个 tot[0..50] 数组、来记录:当

前决策点前、格调为 x的客栈数量,记为 tot[x] ; 以及用last[0..50] 来记录:上一个、格调为 x的客栈编号,记为 last[x]。

那么、每次决策时,只要先更新 f的值(即、如果该决策点、符合最低消费要求,则将、最近消费点f、更新为当前决策点);再判

断如果、 f 的值>= last[当前决策点格调] ,即上一个、和决策点 同格调的客栈编号,那么说明:离该点最近的、同格调的客栈、与

决策点之间、有符合最低消费的、客栈。那么就可以将 can[ x]的值更新为 tot[x] (x为当前决策点格调),因为出现的x格调都可记入

方案数。

然后看代码~~~~~

var

last,tot,can:array[0..51] of longint; //3个数组上面都有提到
n,k,p,i,answer,flag,color,cost:longint; //answer记录总方案数,flag为当前决策之前最近的消费点

begin
readln(n,k,p);
for i := 1 to n do begin
readln(color,cost); //采用边读边做,因为所有有用信息均有记录
if cost <= p then flag := i; //更新最近消费点
if flag >= last[color] then can[color]:=tot[color]; //更新 can 数组的值
inc(answer,can[color]); //记录前 i 点、与第 i 点、构成的、符合要求的方案数
inc(tot[color]); //更新tot 数组的值
last[color]:=i; //更新last 数组的值
end;

writeln(answer);

end.

Ps:因为对于每个客栈,f 更新一次,并将该客栈格调相关数组值更新,所以是相当科学的~~~~~~~~~~~~~~~~~

srO 附: 嘘嘘大神原题解链接 Orz

srO http://www.cnblogs.com/oxxxo/p/3370853.html Orz
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: