代码优化子集总和

Code optimization subset sum

本文关键字:子集 代码优化      更新时间:2023-10-16

这是我的代码,它打印了子集的元素,其总和等于给定总和(仅适用于正数):

#include <bits/stdc++.h>
using namespace std;
void traverse(vector<int> vec) {
    for(int a=0; a < vec.size(); a++)
        cout << vec[a] << " ";
    cout << endl;
}
void possible(vector<int> vec, int sum, vector<int> now) {
    if(sum == 0) {
        traverse(now);
    }
    else if(sum < 0) {
        now.clear();
    }
    else if(sum > 0 && vec.size() > 0) {
        for(int a = 0; a < vec.size(); a++) {
            now.push_back(vec[a]);
            vector<int> vecc(vec.begin() + a + 1, vec.end());
            possible(vecc, sum - vec[a], now);
            now.erase(now.end() - 1);
        }
    }
}
int main() {
    int n, sum;
    cin >> n >> sum;
    vector<int> vec(n), now;
    for(int a = 0; a < n; a++)
        cin >> vec[a];
    possible(vec, sum, now);
    return 0;
}

是否有任何改进或更快地改善运行时间的方法?

对此有任何动态问题解决方案?

子集总和问题可以通过动态编程来解决,因为您可以在动态编程中阅读|设置25(子集总和问题)。

问题是事实上的NP完整(对于此问题没有已知的多项式时间解决方案)。上面的链接提供了两种解决方案,其中第二个可以在 pseudo-polynomial时间

中解决问题。

作为技术优化,您可以更改此信息:

void traverse(vector<int> vec)

void traverse(vector<int>& vec)

为了避免使用潜在的大量载体的非账户副本。如果可以的话,请执行所有功能。


启用警告(例如,用于GCC的-Wall -Wextra),并修复这些警告。然后考虑性能。


ps:为什么我不应该#include&lt; bits/stdc 。h&gt;?

似乎有效的递归动态编程解决方案(尽管我尚未对其进行彻底测试)。它也可以处理负数。

// To make it simple, returns empty vector if no solution was found
// and also if the sum is zero
std::vector<int> find(const std::vector<int>& numbers, int sum)
{
    std::vector<int> result;
    if (findNumbersMakingSum(numbers, sum, result, 0)) {
        return result;
    } else {
        return std::vector<int>();
    }
}
bool findNumbersMakingSum(
    const std::vector<int>& numbers,
    int sumLeft,
    std::vector<int>& takenNumbers,
    size_t position)
{
    if (!sumLeft) {
        // We're done
        return true;
    }
    if (position == numbers.size()) {
        return false;
    }
    int current = numbers[position];
    if (!current) {
        // Just skip zero elements
        return findNumbersMakingSum(numbers, sumLeft, takenNumbers, position + 1);
    }
    // Case 1: take number at current position:
    takenNumbers.push_back(current);
    if (findNumbersMakingSum(numbers, sumLeft - current, takenNumbers, position + 1)) {
        return true;
    }
    // Case 2: don't take number at current position
    takenNumbers.pop_back();
    return findNumbersMakingSum(numbers, sumLeft, takenNumbers, position + 1);
}

由于它是递归的,因此,由于有限的呼叫堆栈,它将失败。该解决方案可以轻松更新以不使用递归,但我希望这个想法很清楚。

在本Wikipedia文章中提到了一个动态编程解决方案;它通过获得状态空间的两个轴来使用目标值的"组合化"。第一个轴是项目的初始间隔,而第二轴是所需的目标值。