基础算法学习笔记
贪心
原理
过程和解法
证明:反证法(交换元素后,答案不会变好)/归纳法(类似递推,最优推最优)
题型或途径:排序然后取(离线)/取当前最__的值更新(在线)
解法:排序/后悔
与DP的界限
贪心是更强的DP。例如上面题目用DP解法会显然地MLE,但是观察到性质之后就可以贪心+Data Structure 达到 \(N\log N\) .
贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。
—— OI Wiki
Johnson法则
物品i与j在A和B台机器上加工,只能先被机器A加工后被机器B加工。记物品k在A机器加工须用时\(a_k\),在B机器加工须用时\(b_k\)。
证明:当物品i,j满足 \(min(a_i,b_j)<min(a_j,b_i)\) 时,先加工i可以得到最优解。
证明:
假设有2台机器A和B,有2件物品i和j,加工完成物品所需时间为\(T(i,j)<T(j,i)\).
易知加工总时间
则因为先加工i可以使所需时间更短,所以先加工i时,B机器的等待时间更少。
则
上文中\(min(a_i,b_j)<min(a_j,b_i)\)为Johnson法则的数学表达式,这种论证方法即为交换论证。
Huffman 树
用 \(n\) 个结点(都做叶子结点且都有各自的权值)试图构建一棵树,如果构建的这棵树的带权路径长度最小:称其为“最优二叉树”=“哈夫曼树”。
参考文章
- 从零开始学贪心算法
- Johnson法则证明
- OI Wiki
二分
感谢《算法竞赛进阶指南》,我遇到了救星/(ㄒoㄒ)/
据说,只有10%的程序猿能写对二分。
为什么二分
因为根据复杂度理论,判定的难度小于求解。
整数域上的二分
我们喜欢让循环在\(l==r\)时停止,所以采用的终止条件是l<r
.
在单调递增序列a
上查找\(\geq x\)的数中最小的一个
while(l<r){
int mid=(l+r)>>1;
if(a[mid]>=x) r=mid;
else l=mid+1;
}
return a[l];
在单调增序列a
上查找\(\leq x\)的数中最大的一个
while(l<r){
int mid=(l+r+1)>>1;
if(a[mid]<=x) l=mid;
else r=mid-1;
}
return a[l];
注意:
- \(mid=(l+r)\gg 1;\)
\(\gg\)后是向下取整,而\(/2\)是向0取整。当二分的区间包含负数时,用\(/2\)易出锅⚠ - 请配套使用
不难发现上文有两种套装:
"\(l=mid+1, r=mid, mid=(l+r) \gg 1\)" \((I)\)
"\(l=mid, r=mid-1, mid=(l+r+1) \gg 1\)" \((II)\)
方法\(I\)的特点是,\(mid\) 不会取到 \(r\) 这个值,因此在区间 \([l,r]\) 中可能二分出的答案区间为 \([l,r)\)。我们可以通过将初始的区间设为 \([l,r+1]\) 来让答案区间变为 \([l,r]\)。
同样地,方法\(II\)中,把最初的二分区间改为 \([l-1,r]\) 即可。
USACO的Silver很喜欢二分,例如这道#10012. 「一本通 1.2 例 2」Best Cow Fences。
这道题的思路是,二分答案,找到可以实现的最大平均数。
下次看到求序列某奇奇怪怪数学最值时,记得二分答案噢。
实数域上的二分
eps
看情况设,一般1e-7
、1e-8
就差不多了- 实测:相同语句下
r-l>eps
会无法终止循环,而l+eps<r
可以,可能是精度问题(eps=1e-7
)。
while(l+eps<r) {
db mid=l+(r-l)/2;
// mid=(l+r)/2 也可以
if(chk(mid)) l=mid;
else r=mid;
}
王钦石wqs二分
三分
人类的本质是口嗨与卷(确信)。我们用二分解决直线上的问题,用三分解决平面上的问题,那么是否可以四分来求空间图形的特征点……
若果然如此,二分岂不是与平方反比的引力一样,因为我们在三维世界,所以有\(x^{3-1}\)反比定律,用\(x^{3+1}\)分法解决问题,etc.
那就Dream一些 \(n\)分天下 的题咯QwQ