And*_*zos 5 algorithm np-complete
请考虑以下问题:
N个硬币编号为1到N.
你看不到它们,但是给出了关于它们的M个事实:
struct Fact
{
set<int> positions
int num_heads
}
Run Code Online (Sandbox Code Playgroud)
positions识别硬币的子集,并且num_heads是该子集中作为头的硬币数.
鉴于这些M个事实,你需要计算出可能存在的最大头数.
这个问题NP完全吗?如果是,减少量是多少?如果不是,什么是多项式时间解?
例如:
N = 5
M = 3
fact1 = { {1, 2}, 1 } // Either coin 1 or coin 2 is a head
fact2 = { {4}, 0 } // Coin 4 is a tail
fact3 = { {2, 4, 5}, 2 } // Out of coins 2, 4 and 5, two are heads
Run Code Online (Sandbox Code Playgroud)
最符合事实的头部配置是:
T H H T H
Run Code Online (Sandbox Code Playgroud)
所以答案是3个头.
假设您有 3-SAT 问题。您可以将该问题中的每个布尔变量 v 映射到两个硬币。称它们为“true(v)”和“false(v)”。这个想法是,如果 3-SAT 问题的解中的 v 为真,则“true(v)”为正面;否则 'false(v)' 为正面。对于每个 v,您添加硬币约束
{true(v), false(v)} has 1 heads, and has 1 tails
Run Code Online (Sandbox Code Playgroud)
之后,您可以翻译带有文字 l1、l2、l3 的 3-SAT 子句
l1 or l2 or l3
Run Code Online (Sandbox Code Playgroud)
到硬币约束
{t/f(l1), t/f(l2), t/f(l3)} has at least 1 heads
Run Code Online (Sandbox Code Playgroud)
其中 t/f(l1) 是“true(l1)”或“false(l1)”,具体取决于子句中 l1 是正数(未否定)还是负数(否定)。我们只需要证明“至少 1 个正面”可以在硬币问题中实现,因为“至少 1 个正面”无法直接表达。这可以通过以下设备来完成。令 C1、C2、C3 为三枚硬币,我们要对其声明约束“其中至少有一个是正面”。创建另外三个硬币 X1、X2、X3 并放入约束中
{X1, X2, X3, C1, C2, C3} has 4 heads
Run Code Online (Sandbox Code Playgroud)
但 X1、X2、X3 没有其他约束。仅当C1、C2、C3中至少有一个是正面时才满足该约束;硬币X1..3可用于提供剩余所需的头。
请注意,这种减少根本没有使用问题的“最大头数”方面;如果 3-SAT 公式不可满足,那么显然根本不可能为代表布尔变量的硬币选择正面/反面状态。
这是从 3-SAT 到硬币问题的多项式约简,表明它是 NP 困难的。为了证明它是 NP 完全的,只需观察硬币问题的解决方案可以在多项式时间内(QED)进行检查。