背包问题 算法

#include <iostream>
#include <stdio.h>
#include <vector>
#include <list>
#include <algorithm>
#include <functional>
#include <math.h>
#include "MaxSubarray.h"

/************************************************************************/
/*    分治法
    最大和子数组有三种情况:
    1)A[1...mid]
    2)A[mid+1...N]
    3)A[i..mid..j]
/************************************************************************/
int Find_Max_Crossing_Subarray (int a[],int low, int mid, int high)
{
    int left_sum = INT_MIN;
    int right_sum = INT_MIN;

    int max_left = -1, max_right = -1;
    int sum = 0;
    for ( int i = mid; i >= low; i-- )
    {
        sum += a [i];
        if (sum > left_sum)
        {
            left_sum = sum;
            max_left = i;
        }
    }
    sum = 0;
    for ( int j = mid + 1; j <= high; j++ )
    {
        sum += a [j];
        if (sum>right_sum)
        {
            right_sum = sum;
            max_right = j;
        }
    }
    std::cout << left_sum + right_sum << std::endl;;
    return ( left_sum + right_sum );
}

int Find_Maximum_Subarrary ( int a[], int low, int hight )
{
    if (low==hight)
    {
        std::cout << a [low]<< std::endl;
        return a [low];
    }
    else
    {
        int mid = ( low + hight ) / 2;
        int leftsum = Find_Maximum_Subarrary ( a, low, mid );
        int rightsum = Find_Maximum_Subarrary ( a, mid+1, hight );
        int crosssum = Find_Max_Crossing_Subarray ( a, low, mid, hight );
        if (leftsum>=rightsum && leftsum > crosssum)
        {
            return leftsum;
        }
        else if ( rightsum >= leftsum && rightsum > crosssum )
        {
            return rightsum;
        }
        else
            return crosssum;
    }
}

/************************************************************************/
/*    区间法    不能每次都求出最大子数组?? 有个条件不对
    求A[1...j+1]的最大和子数组,有两种情况:
    1)A[1...j]的最大和子数组
    2)某个A[i...j+1]的最大和子数组
/************************************************************************/
void MaxSubArraySum_Greedy ( int arr[], std::vector<int> &subarr, int len )
{
    if ( len == 0 )
    {
        return;
    }
    int nmax = INT_MIN;
    int low = 0, high = 0;
    int cur = 0;    // 一个指针更新子数组的左区间
    int nsum = 0;
    for ( int i = 0; i < len;i++ )
    {
        nsum += arr [i];
        if ( nsum > nmax ) // 当和在增加时,区间向右增大
        {
            nmax = nsum;
            low = cur;
            high = i;
        }
        if ( nsum<0 )  // 条件不对  当和小于零时,区间向左减小,当和在增加时,区间向右增大
        {
            cur += 1;
            nsum = 0;
        }
    }
    for ( int i= low; i <= high; i++ )
    {
        subarr.push_back ( arr [i] );
    }
}
/************************************************************************/
/*  动态规划(对应着上面的贪心法看,略有不同)
     求A[1...j+1]的最大和子数组,有两种情况:
         1)A[1...j]+A[j+1]的最大和子数组
         2)A[j+1]
     dp递推式:
         sum[j+1] = max(sum[j] + A[j+1], A[j+1])
/***************************************************************/
int MaxSubArraySum_dp ( int arr[], int len )
{
    if (len <=0)
    {
        exit ( -1 );
    }
    int nmax = INT_MIN;
    int sum = 0; 

    for ( int i = 0; i < len; i++ )
    {
        if ( sum >= 0 )
            sum += arr [i];
        else
            sum = arr [i];
        if (sum > nmax)
        {
            nmax = sum;
        }
    }
    return nmax;
}
// 钢条  
#define  get_max(a,b)  (a>=b)?a:b

// 带备忘,自顶向下
int Memoized_Cut_rog_Aux ( int p[], int nlength, int r[] );
int Memoized_Cut_rog ( int p[], int nlength )
{
    int* r  = new int[nlength];
    memset ( r,  INT_MIN, nlength );
    return Memoized_Cut_rog_Aux ( p, nlength, r );
}
int Memoized_Cut_rog_Aux ( int p[], int nlength, int r[] )
{
    int result = INT_MIN;
    if ( r [nlength] >= 0 )
    {
        return r [nlength];
    }
    if (nlength==0)
    {
        result = 0;
    }
    for ( int i = 1; i <= nlength; i++ )
    {
        result = get_max ( result, p [i - 1] + Memoized_Cut_rog_Aux ( p, nlength - i, r ) );
    }
    r [nlength] = result;
    return result;
}



// 无备忘,很慢
int solution (int p[], int nlength )
{
    if (nlength==0)
    {
        return 0;
    }
    int result = INT_MIN;
    for ( int i = 1; i <= nlength; i++ )
    {
        result = get_max ( result, p [i - 1] + solution ( p,nlength - i ) );
    }
    return result;
}

// 背包问题  带备忘,计算耗时短
int GetMaxValueOfWeight_Aux ( int r[], int v[], int  w[], int nsize, int wr );
int GetMaxValueOfWeight ( int v[], int w[],int nsize,int wr )
{
    int *r = new int [wr];
    memset ( r, 0, wr );
    for ( int i = 1; i <= wr; i++ )
    {
        return GetMaxValueOfWeight_Aux ( r, v, w, nsize,wr );
    }
}
int GetMaxValueOfWeight_Aux ( int r[], int v[], int w[], int nsize, int wr )
{
    int result = INT_MIN;
    if (r[wr]>=0)
        return r [wr];
    if (wr==0)
        result = 0;
    for ( int i = 1; i <= wr; i++ )
    {
        int preresult = 0;
        for ( int j = 0; j < nsize; j++ )
        {
            if ( w [j] == wr )    // 查找当前存在的 重量
            {
                // 保存 重量相同时所有的价格
                if ( v [j] >= result )    // 
                    result = v [j];
            }
            if ( w [j] == i )    // 剩下另一部分的长度
            {
                if ( v [j] >= preresult )
                    preresult = v [j];
            }
        }
        result = get_max ( result,  preresult + GetMaxValueOfWeight_Aux ( r, v, w, nsize, wr - i ) );
    }
    r [wr] = result;
    return result;
}
int main ()
{
//     int a[] = { 8,1, -2, 3, 10, -4, 7, 2, -5 };
//     std::cout << Find_Maximum_Subarrary ( a, 0, 9 ) << "    " << std::endl;
// 
//     std::vector<int > subarr;
//     MaxSubArraySum_Greedy ( a, subarr, 9 );
//     for ( int i = 0; i < subarr.size (); i++ )
//     {
//         std::cout << subarr.at ( i ) << "    " << std::endl;
//     }
// 
//     std::cout << MaxSubArraySum_dp ( a, 9 ) << std::endl;
//     int prices[] = { 1, 5, 8, 9, 10, 17, 17, 20, 24, 30,
//         30, 30, 30, 30, 30, 30, 30, 30, 30, 30 ,
//         30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 };
// 
//     for ( int i = 1; i <= 33; i++ )
//     {
//         //std::cout << i << "   " << solution ( prices, i ) << std::endl;
//     //    std::cout << i << "   " << BOTTOM_UP_CUT_ROD ( prices, i ) << std::endl;
//         std::cout << i << "   " << Memoized_Cut_rog ( prices, i ) << std::endl;
//     }
    int Weight[] = { 0,2, 2, 6, 5, 4 };  //物品的重量  
    int Value[] = {0,6, 3, 5, 4, 6 };  //物品的价值  
    for ( size_t i = 1; i <= 10; i++ )
    {
        std::cout << i << "   " << GetMaxValueOfWeight (Value,Weight,6,i ) << std::endl;
    }
    system ( "pause" );
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值