简单背包问题

来源:互联网 发布:中世纪2优化9兵种 编辑:程序博客网 时间:2024/06/05 10:07

出自算法引论-一种创造性方法

1、背包问题:

给定一个整数K和N个大小不同的物品,第i个物品的体积为S[i],寻找一个子集使子集的和大小等于K,或者确定不存在这样的子集


解答:

动态规划,即建立P[n][k](0<=n<=N,0<=k<=K)大小二维数组保存解,根据前面的解P[n-1][k],P[n-1][K-S[n]]的状态来确定。


代码:


const int N =6;//物品数量

int S[N+1] = {0,3,5,6,8,2,4};//物品体积,S[0]无效

const int K =14;//背包大小


typedef struct _state{

    int exist;//是否存在解

    int belong;//是否包含当前S[n]

}state;

state P[N+1][K+1];


int knapsack()

{

    P[0][0].exist = 1;

    std::cout<<"  0 ";

    for (int k =1; k <= K; k++){

        P[0][k].exist =0;

        std::cout<<k<<" ";

    }

    std::cout<<std::endl;

    

    for (int i =1; i <= N; i++){

        std::cout<<S[i]<<" ";

        for (int k =0; k <=K;k++){

            P[i][k].exist =0;

            if (P[i-1][k].exist){

                P[i][k].exist =1;

                P[i][k].belong =0;

            }

            elseif (k-S[i]>=0){

                if (P[i-1][k-S[i]].exist){

                    P[i][k].exist =1;

                    P[i][k].belong =1;

                }

            }

            

            if (P[i][k].belong &&P[i][k].exist)std::cout<<"I ";

            elseif(P[i][k].exist)std::cout<<"O ";

            elsestd::cout<<"- ";

            if (k>=10)

                std::cout<<" ";

            

        }

        std::cout<<std::endl;

    }

    returnP[N][K].exist;

}

2、习题

问题:令x1,x2,。。。xn是一组整数,试找到一个划分这个数组为2部分相等的方法,或者不能做出这样的划分

解答:与背包一样的解法,只是此时背包K的值为(x1+x2+...+xn)/2

代码:

int knapsack_for_sum_mod_2()

{

    P[0][0].exist = 1;

    std::cout<<"  0 ";

    for (int k =1; k <= K; k++){

        P[0][k].exist =0;

        std::cout<<k<<" ";

    }

    std::cout<<std::endl;

    

    for (int i =1; i <= N; i++){

        std::cout<<S[i]<<" ";

        for (int k =0; k <=K;k++){

            P[i][k].exist =0;

            if (P[i-1][k].exist){

                P[i][k].exist =1;

                P[i][k].belong =0;

            }

            elseif (k-S[i]>=0){

                if (P[i-1][k-S[i]].exist){

                    P[i][k].exist =1;

                    P[i][k].belong =1;

                }

            }

            

            if (P[i][k].belong &&P[i][k].exist)std::cout<<"I ";

            elseif(P[i][k].exist)std::cout<<"O ";

            elsestd::cout<<"- ";

            if (k>=10)

                std::cout<<" ";

            

        }

        std::cout<<std::endl;

    }

    

    //打印解

    int n =N;

    int k =K;

    while(n>=1 && k>=0){

        if (P[n][k].exist){

            if (P[n][k].belong){

                std::cout<<S[N]<<" ";

            }

            else{

                for (; n >=1; n--){

                    if (P[n][k].belong){

                        std::cout<<S[n]<<" ";

                        k-=S[n];

                        break;

                    }

                }

            }

        }

        else

            break;

    }

    std::cout<<std::endl;

    

    returnP[N][K].exist;

}





原创粉丝点击