背包问题

来源:互联网 发布:飞狐交易师软件 编辑:程序博客网 时间:2024/06/06 07:13

将一个数组里面的值分成两个数组,并且使这两个子数组的和的差绝对值最小。

典型的 0 1 背包问题

dp[i][j] = max(dp[i-1][j], dp[i-1][j-arr[i-1]])

下面就是代码,并且打印出了回溯的路径。

#include <iostream>#include <cstdlib>#include <cstring>#include <vector>using namespace std;// 0 1 背包问题enum MOVE {LEFT = 1, UP = 2};int max_val(const int &val1, const int &val2){    return val1 > val2 ? val1 : val2;}int main(int argc, char *argv[]){    //int arr[] = {102, 21, 39, 10, 94, 72, 2, 5, 66, 57, 110, 73, 154, 167};    int arr[] = {102, 21, 39, 10, 94, 72, 2, 3, 5, 66, 57, 110, 73, 154, 167};    //int arr[] = {3, 8, 12, 60, 90, 33};    int len = sizeof(arr) / sizeof(int);    std::cout << "array data" << std::endl;    int i = 0;    int sum = 0;    for (i = 0; i < len; i++)    {        std::cout << arr[i] << " ";        sum += arr[i];    }    std::cout << std::endl;    std::cout << "sum: " << sum << std::endl;    int tmp = sum;    sum = sum / 2;    int k = 0;    int **dp;    int **move;    dp = new int *[len+1];    move = new int *[len+1];    memset(dp, 0, sizeof(int *)*(len+1));    memset(move, 0, sizeof(int *)*(len+1));    i = 0;    for (i = 0; i < len+1; i++) {        dp[i] = new int [sum+1];        memset(dp[i], 0, sizeof(int)*(sum+1));        move[i] = new int [sum+1];        memset(move[i], 0, sizeof(int)*(sum+1));    }    int j = 0;    for (i = 1; i <= len; i++)    {        for (j = 1; j <= sum; j++)        {            if (j >= arr[i-1]) {                if (dp[i-1][j] > dp[i-1][j-arr[i-1]] + arr[i-1]) {                    dp[i][j] = dp[i-1][j];                    move[i][j] = UP;                } else {                    dp[i][j] = dp[i-1][j-arr[i-1]] + arr[i-1];                    move[i][j] = LEFT;                }                //dp[i][j] = max_val(dp[i-1][j], dp[i-1][j-arr[i-1]] + arr[i-1]);            } else {                dp[i][j] = dp[i-1][j];                move[i][j] = UP;            }        }    }    std::cout << "the sum: " << dp[len][sum] << std::endl;    std::cout << "the minus: " << tmp - dp[len][sum]*2 << std::endl;    std::cout << "trace back: " << std::endl;    int trace_sum = 0;    i = len;    j = sum;    // trace back    while (i > 0 && j > 0)    {        if (move[i][j] == UP)        {            i--;            continue;        }        if (move[i][j] == LEFT)        {            std::cout << arr[i-1] << " ";            trace_sum += arr[i-1];            // attention the order of the j and i            j = j-arr[i-1];            i--;        }    }    std::cout << std::endl;    std::cout << "trace_sum: " << trace_sum << std::endl;    for (i = 0; i < len+1; i++)    {        delete [] dp[i];        delete [] move[i];        dp[i] = NULL;        move[i] = NULL;    }    delete [] dp;    dp = NULL;    delete [] move;    move = NULL;    return 0;}
原创粉丝点击