Algorithm 线性时间的子集和
这是我们期末考试的一道题。这是逐字逐句的,因为教授让我们把考试的副本带回家Algorithm 线性时间的子集和,algorithm,time-complexity,subset-sum,Algorithm,Time Complexity,Subset Sum,这是我们期末考试的一道题。这是逐字逐句的,因为教授让我们把考试的副本带回家 (20点)设I={r1,r2,…,rn}是一组n个任意正整数,I中的值是不同的。我没有按任何顺序给出。假设我们想要找到I的子集I’,使得I’中所有元素的总和正好是100*ceil(n^.5)(I的每个元素最多只能在I’中出现一次)。提出了一种求解该问题的O(n)时间算法 据我所知,这基本上是背包问题的一个特例,也就是所谓的子集和问题。。。这两个问题在NP中都是线性时间内理论上不可能解决的 所以。。。这是个骗人的问题吗
基本上解释了如果权重有界,则可以进行伪多项式(线性)时间近似,但在考试问题中权重没有界,并且考虑到考试的总体难度,如果教授希望我们知道/想出一个模糊的动态优化算法,我会感到震惊 确定以下是O(n)时间内的一个简单解决方案。 由于所需的和
S
的顺序为O(n^0.5)
,如果我们制定一个复杂度S^2
的算法,那么我们是好的,因为我们的算法将具有有效的复杂度O(n)
int[]FindSubsetToImpliedTarget(int[]输入){
var目标=100*(int)数学上限(Math.Sqrt(inputs.Count));
//建立联系方式表
var达到=新整数?[目标+1];
达到[0]=0;//空集达到0
foreach(输入中的var e){
//我们后退以避免脱离自己
对于(变量i=目标;i>=e;i--){
如果(达到[i-e].HasValue){
达到[i]=e;
}
}
}
//达到目标了吗?
如果(!reach[target].HasValue)返回null;
//通过记录的到达值回溯生成结果
var result=新列表();
对于(变量i=目标;达到[i]!=0;i-=达到[i]。值){
结果.Add(达到[i].值);
}
返回result.ToArray();
}
我还没有实际测试过上面的代码,所以要小心错字和逐个错字。使用典型的DP算法将获得
O(N)
耗时的算法。我们使用dp[i][k]
(布尔值)来指示前i项是否有一个和为k的子集,过渡方程为:
dp[i][k] = (dp[i-1][k-v[i] || dp[i-1][k]),
它是
O(NM)
,其中N是集合的大小,M是目标和。由于元素是不同的,总和必须等于<代码> 100×CEL(n ^ 5)< /> >,我们最多只需要考虑第一个100×CEL(n,5)项,然后得到<代码>,权重确实有界,可以忽略那些大于<代码> 100 *CEL(SqRT(n))< /> >的权重。因此,您可以使用链接到的算法。当没有解决方案时(例如,I={1,2,3,4}
),响应应该是什么?(a) “无解”(b)“最近的解是……”(c)不收敛于O(n)。