zoukankan      html  css  js  c++  java
  • 动态规划(DP),0-1背包问题

    题目链接:http://poj.org/problem?id=3624

    1、p[i][j]表示,背包容量为j,从i,i+1,i+2,...,n的最优解。

    2、递推公式

    p[i][j]=max(p[i+1][j],p[i+1][j-w[i]]+v[i]);

    #include <stdio.h>
    #include <algorithm>
    #include <string.h>
    #define NUM 3410 //物品数量的上限
    #define CAP 1300 //背包容量的上限
    
    using namespace std;
    
    int w[NUM];//物品的重量
    int v[NUM];//物品的价值
    int p[NUM][CAP];//p[i][j]表示背包容量为j时,可选物品为i,i+1,...n时的01背包问题的最优解
    //题意就是求p[1][c];
    
    //递推表达式即为p[i][j]=max(p[i+1][j],p[i+1][j-w[i]]+v[i]);
    //下面递推求出p[1][c];
    void knapsack(int c,int n)//c为背包容量,n为物品的数量
    {
        //计算递推边界
        int jMax=min(w[n]-1,c);
        for(int j=0; j<=jMax; j++)
            p[n][j]=0;//第n个物品,这里都装不下
        for(int j=w[n]; j<=c; j++)
            p[n][j]=v[n];//第n个物品,这里都装得下
        //开始递推计算到p[2][c];
        for(int i=n-1; i>1; i--)
        {
            jMax=min(w[i]-1,c);
            for(int j=0; j<=jMax; j++)
                p[i][j]=p[i+1][j];//装不下
            for(int j=w[i]; j<=c; j++)
                p[i][j]=max(p[i+1][j],p[i+1][j-w[i]]+v[i]);
        }
        p[1][c]=p[2][c];
        if(c>=w[1])
            p[1][c]=max(p[1][c],p[2][c-w[1]]+v[1]);
    }
    
    void traceback(int c,int n,int x[])
    {
        for(int i=1;i<n;i++)
        {
            if(p[i][c]==p[i+1][c])
                x[i]=0;
            else
            {
                x[i]=1;
                c=c-w[i];
            }
        }
        x[n]=(p[n][c])?1:0;
    }
    
    int main()
    {
        int memory[NUM];
        int C,N;///C为容量,N为物品个数
        while(scanf("%d%d",&N,&C)!=EOF)
        {
            memset(p,0,sizeof(p));
            for(int i=1; i<=N; i++)
            {
                scanf("%d",&w[i]);
                scanf("%d",&v[i]);
            }
            knapsack(C,N);
            printf("%d
    ",p[1][C]);
            traceback(C,N,memory);
            for(int i=1;i<=N;i++)
                printf("%d ",memory[i]);
            return 0;
        }
    }

    但是,很遗憾,Runtime Error

    这里可以转化为一维DP

    p[i]表示背包容量为i 时的最优解

    memset(p,0,sizeof(p));

    然后遍历所有物品,更新p

    递推公式:

    for(int i=1;i<=n;i++)
    {
        for(int j=W;j>=1;j--)
        {
            if(j>w[i]&&p[j-w[i]]+val[i]>p[j])
                p[i]=p[j-w[i]]+val[i];
        }
    }

    Source Code

    #include <stdio.h>
    #include <string.h>
    #define N 3500 ///物品数量上限
    #define M 13000///背包容量上限
    
    int w[N];///物品重量
    int val[N];///物品价值
    int p[M];///p[i]表示背包容量为i时的最优解
    int n;///物品个数
    int W;///背包容量
    
    ///求p[W];
    void knapsack()
    {
        int i,j;
        memset(p,0,sizeof(p));
        for(i=1;i<=n;i++)
        {
            for(j=W;j>=1;j--)
            {
                ///当前第i个物品装得下,而且比不装要优
                if(j>=w[i]&&p[j-w[i]]+val[i]>p[j])
                    p[j]=p[j-w[i]]+val[i];
            }
        }
        return ;
    }
    
    int main()
    {
        int i;
        while(scanf("%d%d",&n,&W)!=EOF)
        {
            for(i=1;i<=n;i++)
                scanf("%d%d",&w[i],&val[i]);
            knapsack();
            printf("%d
    ",p[W]);
        }
        return 0;
    }
  • 相关阅读:
    数据字典的设计
    2005年9月全国计算机等级考试二级C语言笔试试题
    2005年4月全国计算机等级考试二级C语言笔试试题
    2004年4月全国计算机等级考试二级C语言笔试试题
    2003年9月全国计算机等级考试二级C语言笔试试卷
    2006年4月全国计算机等级考试二级C语言笔试试题
    2004年9月全国计算机等级考试二级C语言笔试试题
    2006年9月全国计算机等级考试二级C笔试真题及参考答案
    2003年4月全国计算机等级考试二级C语言笔试试题
    2002年9月全国计算机等级考试二级C语言笔试试题
  • 原文地址:https://www.cnblogs.com/TreeDream/p/5248660.html
Copyright © 2011-2022 走看看