算法概论 习题

[[[5.28]]]

假设存在一个最优方案X, 有两个归纳方向可以到达它, 一个是从空集慢慢增加一些点到X, 还有一个是从全集慢慢删除一些点来到达X

前者好像不太好想, 那就试试后者吧

假设当前的点集合为S, 刚开始的时候, S就是所有点的集合. 于是, 问题就是: 我们要删掉最少的点, 使得最后满足题目条件.
然后我们看看, 能不能删掉至少一个点呢(只要删掉一个点都是巨大的进步, 因为即使删掉一个点, 都可以引导我们进入另一个子问题)
假设S里面, 存在一个点vi, 它的度数di < 5, 也就是说, 这个人,它认识的人少于5个. 马上我们就想到, 这个人是绝对不能出现在最后的名单里面的, 因为它认识的人全部加起来都不够5个人, 后面我们无论怎么删, 他认识的人都只会有减无增. 
于是,我们可以很快乐地把这个点从S里面删除, 令 S1 = S - {vi}. 删除以后, 记得更新S1里面的每个点的度数.
于是, 问题转化为, 从S1里面删除最少的点, 使得最后满足题目条件. 子问题成功出现, 递归解决它就行了.

后退一步, 假设S的每个vi的度数di都大于等于5. 既然di >= 5满足了, 那我们看看题目里的另一个条件 -- "不认识的人至少有5个". 
假设对于某个人vi, 他不认识的人小于5个, 跟上面类似的道理, 无论我们删除了哪些点, 这个人到最后不认识的人还是会少于5个, 所以, 这个人是不能留到最后的, 是要删掉的!
删掉这个vi以后, 我们就成功转化为子问题了, 开心地递归就行了.


好了, 继续退一步, 假设S的每个vi的度数di都大于等于5, 并且不认识的人也至少有5个, 那么...........问题本身就已经搞定了:)

于是整个算法就被描述为:
S = 全部点
while (存在某个点vi不符合"认识的人至少有5个而且不认识的人也至少有5个") {
    S = S - {vi}
    更新S里面的每个点的度数
}

输出 S


转载于:https://my.oschina.net/mustang/blog/91343

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值