蓝书例题---数据备份BZOJ1150

博客通过转化问题,将数据备份问题转化为选择不相邻数使和最小的优化问题。对于K=1和K=2的情况给出了直观策略。然后提出使用链表和小根堆的贪心算法解决K等于n的情况。算法过程中,不断更新链表和堆,每次操作保证了子问题的最优解,最终得到整体的最小和。边界条件的处理确保了正确性。
摘要由CSDN通过智能技术生成

问题明显可以转化成:给你n个数,选K个不相邻的数,使其和最小

K==1时,一定选最小值

K==2时,要么选最小+次小

要么选最小旁边的两个数,不可能最小旁边的两个数只选一个,否则为什么不选最小呢?

 

有了这个贪心策略我们就可以搞K==n的情况了。

建一个链表,把这n个数链起来。

再开一个小根堆。

每次操作取出堆顶的数。a[i]

1.把这个数前驱和后继从链表中和堆中删除

2.新建一个权值为这个数前驱和后继的和减去这个数的结点,指向前驱的前驱,后继的后继

3.同时把这个数丢到堆里。

重复上述操作

每次的操作相当于处理一个新的子问题:长度为n-i的序列选出K-i个数,使其和的值最小。

第二次选择id的数时相当于选择其周围2个数,并撤销对id的选择(包括其进行的操作)

比如  id表示:  选46不选5(但此时id的值为:3+7-(4+6-5))   ,如果这时候选择了id相当于选357不选46.

而且保证了每次选择多一个数,每次都是最优解。最终一定也是最优解/

 

注意:最左边前驱和最右边的后继要设成无穷大。

以为一旦选了边界的数,就不可能选次边界的数了,大家可以想一想为啥。


#include <bits/stdc++.h>
using namespace std;
typedef long lon
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值