01背包入门啦………

来源:互联网 发布:电脑拨号软件 编辑:程序博客网 时间:2024/06/08 07:08

作为动态规划中最为基础的内容,需要掌握、熟练,这就是必须的啦
那好,我们先看看什么才是01背包

先由一个最为经典的例题来引我们入门:
     小喵有N个物品和一个背包。物品i的重量是Wi , 其价值位Vi,背包的容量为C。问小喵应该如何选择装入背包的物品,使得装进背包的物品的总价值为最大?
     显而易见,贪心这位并不能帮助我们,我们只能新认识一位朋友,动态家族的01背包。
     这位新朋友告诉我们,这个问题很简单,只需要一个个考虑这第i个物品是要还是不要。
            如图所示
       现在看一下伪代码(:
            for(i从1开始遍历N个物品)
                 for(j从C开始遍历,直到 j < Wi)
                       dp[ j ] = max( dp[ j ], dp[j-Wi]+V[i])
      我们来分析一下代码:
             dp[j]表示没有加进物品 i 时,重量为 j 时此刻的价值的最大值;
             dp[j-Wi]+V[i]表示将第 i 个物品加进背包后重量为 j 时的价值;
             之后判定此时总量为 j 时的最大价值dp[ j ];


       如果现在似懂非懂,那你需要一些简单的例题来捋一下你的思路
       [Bone Collector]http://acm.hdu.edu.cn/showproblem.php?pid=2602
       简单的01背包:告诉你骨头的数量和背包的最大承受量,之后是每个骨头的价值和每个骨头的重量。求背包所能装的最大价值

#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cstdlib>#include <string>using namespace std;int T;int val[1100], vol[1100];int dp[1100];void init(){    memset(val, -1, sizeof(val));    memset(vol, -1, sizeof(vol));    memset(dp, 0, sizeof(dp));}int main(){    int N, V;    int i, j, k;    while(~scanf("%d", &T))    {    while(T--)    {        init();        scanf("%d%d", &N, &V);        for(i = 0; i < N; i++)        {            scanf("%d", &val[i]);        }        for(i = 0; i < N; i++)        {            scanf("%d", &vol[i]);        }        for (i = 0; i < N; ++i)        {            for (j = V; j >= vol[i]; j--)            {                dp[j] = max(dp[j], dp[j-vol[i]]+val[i]);            }        }        printf("%d\n", dp[V]);    }     }    return 0;}

       [Super Jumping! Jumping! Jumping!]http://acm.hdu.edu.cn/showproblem.php?pid=1087
       棋盘游戏,从开始跳到结束截止,每一格都有一个值,你只能跳到比自己所在一格值大的格(开始和结束格不算),求游戏结束后的最大值。这一题的难处应该是它没有背包的最大承受量吧。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstdlib>#include <string>#include <vector>#include <cstring>#define Max 2900using namespace std;int score[Max];int dp[Max], sum;int main(){    int N;    int i, j, k;    while(~scanf("%d", &N) && N)    {        memset(score, 0, sizeof(score));        memset(dp, 0, sizeof(dp));        for(i = 1; i <= N; i++)        {            scanf("%d", &score[i]);        }        dp[0] = 0;        k = 0;        for(i = 1; i <= N; i++)        {            sum = score[i];            for(j = 1; j < i; j++)            {                if(score[i] > score[j])   sum = max(sum, dp[j]+score[i]);            }            dp[i] = sum;            k = max(k, sum);        }        cout << k << endl;    }    return 0;}

       [命运]http://acm.hdu.edu.cn/showproblem.php?pid=2571
       和hdu的1087差不多,不过这个是二维的图,运动方式三种向下一格,向右一格或向右跳现在所在格行的倍数。(!!!中文题)

#include <iostream>#include <cstdio>#include <algorithm>#include <cstdlib>#include <cstring>#include <string>using namespace std;int maza[21][1100];int dp[21][1100];int main(){    int T;    int N, M;    int i, j, k;    bool a;    scanf("%d", &T);    while(T--)    {        scanf("%d%d", &N, &M);        for(i = 1; i <= N; i++)        {            for(j = 1; j <= M; j++)            {                scanf("%d", &maza[i][j]);            }        }        for(i = 1; i <= N; i++)        {            for(j = 1; j <= M; j++)            {                if(i == 1 && j == 1) dp[1][1] = maza[1][1];                else                {                    a = false;                    if(i-1 >= 1)                    {                        dp[i][j] = dp[i-1][j] + maza[i][j];                        a = true;                    }                    if(j-1 >= 1)                    {                        if(a) dp[i][j] = max(dp[i][j], dp[i][j-1]+maza[i][j]);                        else dp[i][j] = dp[i][j-1] + maza[i][j];                        a = true;                    }                    for(k = 1; k < j-1; k++)                    {                        if(j%k != 0) continue;                        else                        {                            dp[i][j] = max(dp[i][j], dp[i][k]+maza[i][j]);                        }                    }                }            }        }        cout << dp[N][M] << endl;    }    return 0;}

           请大家多多指教^^

0 0
原创粉丝点击