【DP】01背包

(精选上好代码讲解产自原装进口白皮书)

01背包问题

有n个重量和价值分别为wi,vi的物品,从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。

首先我们用朴素的方式搜索一遍:

int rec(int i,int j){
    int res;
    if(i==n)  res=0;//已经没有剩余物品了
    else if(j<w[i]) res=rec(i+1,j);//无法挑选这个物品
    else res=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);//挑选和不挑选两种情况都尝试一下
    return res;
}
/*搜索深度为n 时间O(2^n)*/

优化一下(记忆数组)

int dp[maxn][maxn];
int rec(int i,int j){
    if(dp[i][j]>0) return d[i][j];//已经计算过的话直接使用之前的结果
    int res;
    if(i==n) res=0;
    else if(j<w[i]) res=rec(i+1,j);
    else res=max(rec(i+1,j),rec(i+1,j-w[i])+v[i]);
    return dp[i][i]=res;//结果记录在数组中
}

不用递归函数,直接利用递推式:

int dp[maxn][maxn];
void fun()
{
    for(int i = n - 1; i >= 0; i--)
    {
        for (int j = 0; j <= w; j++)
        {
            if(j < w[i])
            {
                dp[i][j] = dp[i + 1][j];
            }
            else
            {
                dp[i][j] = max(dp[i + 1][j], dp[i + 1][j - w[i]] + v[i]);
            }
        }
    }
    cout<<dp[0][w]<<endl;
}

以上DP都是关于i的逆向进行的循环

那么正向定义如下:

if (j<w[i])
    f[i][j] = f[i-1][j]
else
    f[i][j] = max(f[i-1][j], f[i-1][j-w[i]] + v[i])

举个例子

(w,v)//w是重量,v是价值

(2,3)

(1,2)

(3,4)

(2,2)


i\j


0


1


2


3


4


5


0


0


0


0


0


0


0


1


0


0


3


3


3


3


2


0


2


3


5


5


5


3


0


2


3


5


6


-

如图所示,求dp[3][4]=max(dp[2][4],dp[2][1]+4)

有关01背包的练手题~

HDOJ 1159

题意:求最长公共子序列

思路:01背包模板

#include<stdio.h>
#include<string.h>
#define MAX(a,b) (a>b?a:b)
const int MAXN=1010;
int dp[MAXN][MAXN];
char a[MAXN],b[MAXN];
int main(){
while(~scanf("%s%s",a+1,b+1)){
    memset(dp,0,sizeof(dp));
    int i,j;
    for( i=1;a[i];i++){
        for(j=1;b[j];j++){
            if(a[i]==b[j])dp[i][j]=dp[i-1][j-1]+1;
            else dp[i][j]=MAX(dp[i][j-1],dp[i-1][j]);
        }
    }
    printf("%d\n",dp[i-1][j-1]);
}
return 0;}

原文地址:https://www.cnblogs.com/Kohinur/p/9028289.html

时间: 2024-10-10 16:19:02

【DP】01背包的相关文章

USACO Money Systems Dp 01背包

一道经典的Dp..01背包 定义dp[i] 为需要构造的数字为i 的所有方法数 一开始的时候是这么想的 for(i = 1; i <= N; ++i){ for(j = 1; j <= V; ++j){ if(i - a[j] > 0){ dp[i] += dp[i - a[j]]; } } } 状态存在冗余, 输出的时候答案肯定不对 但只需要改一下两个for循环的顺序即可. Source Code: /* ID: wushuai2 PROG: money LANG: C++ */ //

hdu 1561The more, The Better(树形dp&amp;01背包)

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4949    Accepted Submission(s): 2918 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝

poj 3345 Bribing FIPA 【树形dp + 01背包】

Bribing FIPA Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4274   Accepted: 1337 Description There is going to be a voting at FIPA (Fédération Internationale de Programmation Association) to determine the host of the next IPWC (Interna

poj 1837 Balance (dp,01背包)

链接:poj 1837 题意:有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码, 求将钩码挂到钩子上使天平平衡的方法的总数.其中可以把天枰看做一个以x轴0点作为平衡点的横轴 分析:力臂=重量 *臂长 = g[i]*c[j] 当平衡度k=0时,说明天枰达到平衡,k>0,说明天枰倾向右边(x轴右半轴),k<0则左倾 因此可以定义一个 状态数组dp[i][k],意为在挂满前i个钩码时,平衡度为k的挂法的数量. 由于距离c[i]的范围是-15~15,钩码重量的范围是1~25,钩码数量

hdu 4044 GeoDefense (树形dp+01背包)

GeoDefense Time Limit: 12000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 663    Accepted Submission(s): 267 Problem Description Tower defense is a kind of real-time strategy computer games. The goal of towe

Bone Collector(dp 01背包)

Problem Description Many years ago , in Teddy's hometown there was a man who was called "Bone Collector". This man like to collect varies of bones , such as dog's , cow's , also he went to the grave - The bone collector had a big bag with a volu

HDU 3033 I love sneakers! (DP 01背包+完全背包)

Problem Description After months of hard working, Iserlohn finally wins awesome amount of scholarship. As a great zealot of sneakers, he decides to spend all his money on them in a sneaker store. There are several brands of sneakers that Iserlohn wan

poj 2923 状压dp+01背包

好牛b的思路 题意:一系列物品,用二辆车运送,求运送完所需的最小次数,两辆车必须一起走 解法为状态压缩DP+背包,本题的解题思路是先枚举选择若干个时的状态,总状态量为1<<n,判断这些状态集合里的那些物品能否一次就运走,如果能运走,那就把这个状态看成一个物品.预处理完能从枚举中找到tot个物品,再用这tol个物品中没有交集(也就是两个状态不能同时含有一个物品)的物品进行01背包,每个物品的体积是state[i],价值是1,求包含n个物品的最少价值也就是dp[(1<<n)-1](dp

DP(01背包) UESTC 1218 Pick The Sticks (15CCPC C)

题目传送门 题意:长度为L的金条,将n根金棍尽可能放上去,要求重心在L上,使得价值最大,最多有两条可以长度折半的放上去. 分析:首先长度可能为奇数,先*2.然后除了两条特殊的金棍就是01背包,所以dp[now][j][k]表示当前状态,长度为j,使用了k条特殊金棍获得的最大价值,需要对内存和时间优化. /************************************************ * Author :Running_Time * Created Time :2015/10/2

hdu 1171 Big Event in HDU(dp 01背包 母函数)

01背包 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> using namespace std; int v[100],m[100]; int dp[300000]; int main() { int n; int i,j,k; while(scanf("%d",&n)!=EOF) {