解题报告 B_station
1. 题目
B_station
在离著名的国家Berland不远的地方,有一个水下工作站。这个工作站有N层。已知:是第i层装有Wi的水,最多可以容纳Li的水,恐怖分子炸毁第i层的代价是Pi。第i层一旦被炸毁,该层所有的水都将倾泻到第i+1层。如果某一层的水量超过了它的容量(即Li),那么该层就将自动被毁坏,所有的水也会倾泻到下一层。
Pivland的恐怖分子想要用最少的钱毁掉第N层,现在他雇佣你来计算,需要炸毁哪些层。
输入:第一行有一个自然数N(1<=n<=15000)。接下来的N行,每行3个整数Wi, Li, Pi(0<=Wi,Li,Pi<=15000)。
输出:输出需要炸毁的层的编号。
样例Input 样例output
3 1
1000 1000 1 2
0 1000 2
2 10 100
2. 题目实质
这个题讲的也很明白。
3. 算法
首先,不要一看见最优值就认为是动规,这个题找状态......
其实,他是一个枚举。
选择枚举对像:不妨设恐怖分子炸毁的最高层是第p层(第一层是最高层,第N层是最底层)。
因为恐怖分子的目标是毁灭第N层,所以水必须从第p层一直泻下去。如果存在一个i,满足Wp+Wp+1+…+Wi-1+Wi<=Li,也就是说前面几层的水全部泄下来也无法把第i层自动冲毁,那么就必须要使用***把它炸开了。
考察: Wp+Wp+1+…+Wi-1+Wi<=Li
这个式子要求一段的数字和,为了快速,用前缀和:
令Si=W1+W2+…+Wi(特别的S0=0)。
上式可表示成: Si-Sp-1 <=Li
所以恐怖分子需要炸毁的层的集合就是Bomb[p]={p}∪{i |i>p Si-Sp-1<=Li}
我们枚举p,然后看哪些层需要炸毁。这样就得到了一个O(n2)的算法。
然后,这里主要讲一下优化:
剪枝:在你枚举的时候,在内层循环中记录一下当前炸了这么多层已经花了多少钱,当这个数目大于已经记录的最小值时, break 。(这样就能过)
记忆化:当搜到了一层的时候,已经可以自己冲垮而不用花钱,那么显然将炸的最高层再往上抬,它还是不用花钱,此时就需要将它记录下来,以后不用搜了。也可以在每次需要花钱的时候,记录下还有多少水就可以不用花钱了,到 0 的时候也就不用再搜了。
单调性优化:(大根堆、二分查找、单调队列 etc)
Bomb[p]={p}∪{i |i>p Si-Sp-1<=Li} è
令Qi=Si-Li,那么:
Bomb[p]={p}∪{i |i>p Qi<=Sp-1}
注意到Sp是随着p的增加而递增的(单调性),观察两个集合:
Bomb[p]={p}∪{i |i>p Qi<=Sp-1}
Bomb[p-1]={p-1}∪{i |i>p-1 Qi<=Sp-2}
因为Sp-2<=Sp-1,所以{i |i>p-1 Qi<=Sp-2}包含于 Bomb[p],也就是说,Bomb[p-1]是在Bomb[p]的基础上,通过以下操作得到的:
删除所有的i∈Bomb[p],Qi>Sp-2。(所以找最大值,删除判断就行了)
添加p-1。
针对这两种操作,我们可以使用大根堆(Heap)(单调队列、二分查找什么的都行)。从大到小枚举p,对于每一个p,执行:
Step1. 如果堆的根i满足Qi >Sp-2,那么删除根;否则转Step3。
Step2. 转Step1。
Step3. 添加p-1。
每层至多进堆一次、出堆一次,所以总的时间复杂度是O(nlogn)。对于n<=15000的范围完全能够胜任了。
4. 注意事项
不要一看到最优值就写动规,也适当想一想基础算法。
注意观察数据范围,不要每次一上来就写最厉害(一般也是最难写)的优化,优化优化的不好就会变成退化了,像这个题,三个优化中有一个就可以 AC 。
5. 代码
只用了第一个优化,刚好能过(SueMiller)
var n:longint;
i,j,k:longint;
w,l,p:array[0..15001]of longint;
v,vv:array[0..15001]of boolean;
ans,temp,co:longint;
begin
assign(input,'station.in');reset(input);
assign(output,'station.out');rewrite(output);
fillchar(w,sizeof(w),0);
fillchar(l,sizeof(l),0);
fillchar(p,sizeof(p),0);
readln(n);
for i:=1 to n do
begin
readln(w[i],l[i],p[i]);
end;
if w[n]>l[n] then begin
writeln(0);
close(input);close(output);
halt;
end;
temp:=w[n];
k:=n;
while temp<=l[n] do
begin
dec(k);
temp:=temp+w[k];
end;
ans:=p[n];
fillchar(v,sizeof(v),false);
fillchar(vv,sizeof(vv),false);
vv[n]:=true;
for i:=k downto 1 do
begin
temp:=w[i];
if temp<=l[i] then
begin
co:=p[i];
v[i]:=true;
end;
for j:=i+1 to n do
begin
if temp+w[j]>l[j] then begin
temp:=temp+w[j];
continue
end
else begin
co:=co+p[j];
v[j]:=true;
temp:=temp+w[j];
if co>ans then begin
fillchar(v,sizeof(v),false);
break;
end;
end;
end;
if co<ans then
begin
vv:=v;
ans:=co;
fillchar(v,sizeof(v),false);
end;
end;
writeln(ans);
for i:=1 to n do
if vv[i] then write(i,' ');
writeln;
// temp:=0;
// for i:=1 to n do
// if vv[i] then begin
// temp:=temp+p[i];
// end;
// writeln(temp,' ##');
close(input);close(output);
end.
大根堆 (Liukeke)
program liukeke;
var
w,p,l,s,q:array[0..15001] of longint;
f:array[0..15001] of longint;
ans:array[0..15001] of longint;
m,ans0,anscost,cost,i,n:longint;
procedure downsift(x:longint);
var
k,temp:longint;
begin
temp:=f[x];
k:=x<<1;
while k<=m do
begin
if(k<m)and(q[f[k]]<q[f[k+1]]) then inc(k);
if q[temp]<q[f[k]] then
begin
f[x]:=f[k];
x:=k;
k:=x<<1;
end
else break;
end;
f[x]:=temp;
end;
procedure upsift(x:longint);
var
k,temp:longint;
begin
temp:=f[x];
k:=x>>1;
while k>0 do
begin
if q[temp]>q[f[k]] then
begin
f[x]:=f[k];
x:=k;
k:=x>>1;
end
else break;
end;
f[x]:=temp;
end;
procedure sort(l,r:longint);
var
i,j,mid,temp:longint;
begin
i:=l;j:=r;mid:=ans[(l+r)>>1];
repeat
while ans[i]<mid do inc(i);
while ans[j]>mid do dec(j);
if i<=j then
begin
temp:=ans[i];
ans[i]:=ans[j];
ans[j]:=temp;
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
begin
assign(input,'station.in');reset(input);
assign(output,'station.out');rewrite(output);
readln(n);
for i:=1 to n do
readln(w[i],l[i],p[i]);
for i:=1 to n do
s[i]:=s[i-1]+w[i];
for i:=1 to n do
q[i]:=s[i]-l[i];
m:=1;
f[1]:=n;
cost:=p[n];
anscost:=p[n];
for i:=n downto 2 do
begin
//
while (q[f[1]]>s[i-2])and(m>0) do
begin
dec(cost,p[f[1]]);
f[1]:=f[m];
dec(m);
downsift(1);
end;
//
inc(m);
f[m]:=i-1;
upsift(m);
//
inc(cost,p[i-1]);
if cost<anscost then
begin
anscost:=cost;
ans:=f;
ans0:=m;
end;
end;
//outit;
sort(1,ans0);
writeln(anscost);
for i:=1 to ans0 do
write(ans[i],' ');
close(input);
close(output);
end.
转载于:https://www.cnblogs.com/SueMiller/archive/2011/10/11/2207761.html
解题报告 B_station相关推荐
- uscao 线段树成段更新操作及Lazy思想(POJ3468解题报告)
线段树成段更新操作及Lazy思想(POJ3468解题报告) 标签: treequerybuildn2cstruct 2011-11-03 20:37 5756人阅读 评论(0) 收藏 举报 分类: ...
- 解题报告(十八)数论题目泛做(Codeforces 难度:2000 ~ 3000 + )
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...
- 【解题报告系列】超高质量题单 + 题解(ACM / OI)超高质量题解
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我新写的超高质量的题解和代码,题目难度不 ...
- 解题报告(三)多项式求值与插值(拉格朗日插值)(ACM / OI)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...
- 解题报告(十三)中国剩余定理(ACM / OI)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...
- 解题报告(四)生成函数(ACM/ OI)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量的题解和代码,题目难度不一 ...
- 解题报告(八) prufer 序列与 Cayley 公式(ACM / OI)超高质量题解
繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...
- 解题报告(一)E、(BZOJ4589)Hard Nim(博弈论 + FWT)
繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...
- 解题报告(五)组合计数(ACM / OI)超高质量题解
繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...
最新文章
- AcornCharts
- 5G NGC — 关键技术 — R15 SBA
- java.lang包—StringBuffer类和StringBuilder类
- Windows系统程序设计之结构化异常处理
- Java基础知识——Java数组详解
- runloop - 面试题
- C#LeetCode刷题之#824-山羊拉丁文​​​​​​​(Goat Latin)
- php数组连起来,PHP 数组的拼接重组
- 关系数据库第一第二第三范式
- 大牛总结的 Git 使用技巧,写得太好了!
- EDA技术实用教程 | 复习六 | 过程语句always
- 21天学通mysql_《21天学通JavaWeb》 - 随笔分类 - 疯狂delphi - 博客园
- 使用Netsparker扫描及**某站点
- Linux - ZModem协议的sz命令传输文件异常
- Mac上qmc0文件转码为mp3
- 笔记本输字母p出现仅计算机,电脑打不了字只有字母怎么办?最简单的解决方法...
- 用于实时视频和图像去雾的优化对比度增强算法
- 为什么90%的人物画像都是没用的?
- unity 控制对象移动、旋转
- POM 文件中 licenses 许可证的定义
热门文章
- 蓝桥杯 BEGIN-2 入门训练 序列求和
- LeetCode 515. Find Largest Value in Each Tree Row
- perl调用shell命令并获取输出
- zookeeper安装与测试
- Javascript获取select下拉框选中的的值
- Java 里面 final 与 static
- Android Jni开发,报com.android.ide.common.process.ProcessException: Error configuring 错误解决方案...
- Java各层之间的关系
- BZOJ1433[ZJOI2009]假期的宿舍——二分图最大匹配
- Atitit 外包管理规范attilax总结