子集对应,也称为“子集总计”问题,是一个示例性的 NP 完全计算问题。给定一堆数字和一个客观价值,任务是确定是否存在其总数等于客观价值的数字子集。该问题的 NP 顶峰源于其通过多项式时间递减来解决各种其他 NP 完全问题的能力。不管其简单的定义如何,没有一种有效的计算可以解决所有事件的“子集对应”,这使得它在假设的软件工程和简化中具有重要意义,并且在不同领域(如密码学、资产分配和动态问题)具有功能应用。
使用的方法
-
子集总和的减少
-
从 3SAT 减少
从子集总和中减少
处理“子集公平性”是 NP 完成问题的一种方法是显示显着的 NP 完成问题(“子集总数”问题)的减少。
算法
-
给定一个“子集聚合”问题的案例,它是一堆整数 S 和一个价值 T 的目标。
-
使用类似的集合 S 和目标自尊 2T 来制作“子集权益”问题的另一个案例。
-
如果在“子集聚合”问题中存在 S 的子集汇总为 T,那么此时,“子集均匀性”问题中将存在一个汇总为 T 的子集2T 通过添加与其自身相似的子集。
-
假设在“子集总计”问题中不存在 S 的子集汇总为 T,那么在“子集公平性”问题中也不存在汇总为 2T 的子集,因为任何具有总计的子集低于2T的与其自身相加不能超过2T。
-
这种下降表明解决“子集公平性”问题与解决“子集聚合”问题几乎一样困难,使其成为 NP 完全问题。
示例
#include
#include
using namespace std;
bool isSubsetSum(vector& set, int n, int sum) {
if (sum == 0) return true;
if (n == 0) return false;
if (set[n - 1] > sum) return isSubsetSum(set, n - 1, sum);
return isSubsetSum(set, n - 1, sum) || isSubsetSum(set, n - 1, sum - set[n - 1]);
}
bool isSubsetAggregateReduction(vector& set, int n, int sum) {
return !isSubsetSum(set, n, sum) && !isSubsetSum(set, n, 2 * sum);
}
int main() {
vector set = {3, 34, 4, 12, 5, 2};
int sum = 18;
if (isSubsetAggregateReduction(set, set.size(), sum)) {
cout