• 背包问题


    1 01背包问题

    有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

    解法:我们用dp[i][j]表示前i件物品重量不超过j的最大价值,则dp方程为

    j>w[i]时,dp[i][j]=max{dp[i-1][j],dp[i-1][j-w[i]]+c[i]}

    j<=w[i]时,dp[i][j]=dp[i-1][j].

    其中dp[i-1][j]表示第i件物品无法放在背包里的价值,dp[i-1][j-w[i]]+c[i]表示第i件物品放入背包里的最大价值,我们选择其中的较大的。

    优化:

    采用一维数组来优化dp[v],我们必须保证dp[v]及dp[v-w[i]]是前一个状态的值,及前i-1件物品的最大价值,如何保证这个无后效性呢,采用逆序

    dp[v]=max{dp[v],dp[v-w[i]]+c[i]},这样计算出来的每一个新的dp[v]都不会影响当前循环的后面的结果,核心代码:

    for(i=1;i<=n;i++)

    for(v=V;v>=w[i];v--)

    dp[v]=max{dp[v],dp[v-w[i]]+c[i]};

    2.完全背包

    有N种物品和一个容量为V的背包,每种物品都有无限件可用。第i种物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

    解法:

    仍然采用刚才的思路,用dp[i][j]表示前i件物品重量不超过j的最大价值,则dp方程为:

    dp[i][j]=max{dp[i-k*w[i]]+k*c[i]},0<=k*w[i]<=j

    我们对这个也采用一维数组进行优化,令dp[v]表示dp[i][v],由于这个问题中物品是无穷件,所以我们不用考虑前一个状态,只考虑当前状态,即

    for(i=1;i<=n;i++)

    for(v=w[i];v<=V;v++)

    dp[v]=max{dp[v],dp[v-w[i]]+c[i]};

    这个和01背包的区别就是因为物品是无限的,我们可以累计的将第i件物品加入到当前状态中。

    3.多重背包

    有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

    dp方程为:dp[i][j]=max{dp[i-1][j-k*w[i]+k*c[i]]},0<=k<=n[i]

    对应这个题,由于物品件数有限,我们需要遍历一遍n[i],即将k个第i件物品放入当前背包,选择最大的那个。

    for(i=1;i<=n;i++)

    for(j=0;j<n[i];j++)//即循环n[i]次,选择最大的dp[v]

    for(v=V;v>=w[i];v--)

    dp[v]=max{dp[v],dp[v-w[i]]+c[i]};

    poj1276 ,多重背包问题,但是由于数比较大超时了,必须经过优化,以后有时间再看吧,下面是我超时的代码:

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    const int N=100001;
    int dp[N+2],weight[N],num[N],total,n;
    int main()
    {
    	int i,j,k;
    	while(scanf("%d%d",&total,&n)!=EOF)
    	{
    		for(i=1;i<=n;i++)
    			scanf("%d%d",&num[i],&weight[i]);
    		for(i=0;i<=total;i++)
    			dp[i]=0;
    		if(!total || !n)
    		{
    			printf("%d\n",0);
    			continue;
    		}
    		for(i=1;i<=n;i++)
    		{
    			for(j=0;j<num[i];j++)
    			{
    				for(k=total;k>=weight[i];k--)
    				{
    					if(dp[k]<(dp[k-weight[i]]+weight[i]))
    						dp[k]=dp[k-weight[i]]+weight[i];
    				}
    			}
    		}
    		printf("%d\n",dp[total]);
    	}
    	return 0;
    }
    


  • 相关阅读:
    Python基础语法
    理解session和cookie
    应用服务器
    web服务器
    Python正则表达式
    理解HTTP协议
    常见浏览器内核
    python中range()和len()函数区别
    多线程执行测试用例
    selenium+Python(生成html测试报告)
  • 原文地址:https://www.cnblogs.com/buptLizer/p/2213676.html
Copyright © 2020-2023  润新知