【HDU 2602】DP | 背包 | 01背包 | E

                                   HDU 2602   Bone Collector

                         Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                               Total Submission(s): 81087    Accepted Submission(s): 33534

URL

http://acm.hdu.edu.cn/showproblem.php?pid=2602

Introduction

裸01背包,求最大价值

Input

T组,T唯一,每组依次输入种类数n、背包体积、n种价值、n种体积

Output

每组输出最大价值,带回车

Sample Input

1 5 10 1 2 3 4 5 5 4 3 2 1
 

Sample Output

14
 

Analysis

裸01背包:

  • 可以开二维数组进行dp
    • 初始化:dp清0
    • 数组索引:行数 i 代表当前已安排第 1-i 项物品的存放与否, 列数 v 代表当前体积上限
    • 循环:i:[ 1->n ],v:[ MAXVOL->vol[i] ] 或 [ vol[i]->MAXVOL ]
    • 状态转移方程:dp[i][v] = max { dp[i-1][v-vol[i]]+val[i], dp[i-1][v] },即装第 i 件物品或不装
  • 也可开一维数组进行dp,优化空间复杂度
    • 可优化原因:每次计算 dp[i][v] 时都只会利用上一行的、处于当前项正上方和左上方的项,因此如果每行都从右侧开始遍历,则可将 n 行简化为1行。
    • 初始化:dp清0
    • 数组索引: v 代表当前体积上限
    • 循环:v:必须[MAXVOL->vol[i]] ,自右侧开始循环递减

    • 状态转移方程:dp[v] = max { dp[v-vol[i]]+val[i], dp[v] },即装第 i 件物品或不装

AC code

以下是一维数组进行dp的代码

/** HDU 2602 01背包
 *  by Kevin.
 */
#include <cstdio>
#include <cstring>

#define _SN(x) do{char _c=getchar(),_v=1;for(x=0;_c<48||_c>57;_c=getchar())if(_c==45)_v=-1;for(;_c>=48&&_c<=57;x=(x<<1)+(x<<3)+_c-48,_c=getchar());x*=_v;}while(0)
#define _SAN(a,n) do{int _i=0,_n=n;for(;_i<_n;++_i)_SN(a[_i]);}while(0)
#define _SA(a,l,r) do{int _i=l,_r=r;for(;_i<_r;++_i)_SN(a[_i]);}while(0)
#define _gS(_1,_2,_3,_sc,...) _sc
#define sc(...) _gS(__VA_ARGS__,_SA,_SAN,_SN,...)(__VA_ARGS__)
#define _F0N(i,n) for(int i=0,_n=n;i<_n;++i)
#define _FLR(i,l,r) for(int i=l,_r=r;i<_r;++i)
#define _gF(_1,_2,_3,_F,...) _F
#define F(...) _gF(__VA_ARGS__,_FLR,_F0N,...)(__VA_ARGS__)
#define _FD0(i,n) for(int i=0,_n=n;i<=_n;++i)
#define _FDL(i,l,r) for(int i=l,_r=r;i<=_r;++i)
#define _gFD(_1, _2, _3, _FD, ...) _FD
#define FD(...) _gFD(__VA_ARGS__, _FDL, _FD0, ...)(__VA_ARGS__)
#define mem0(a) memset(a,0,sizeof(a))
#define memf1(a) memset(a,-1,sizeof(a))
#define meminf(a) memset(a,0x7F,sizeof(a))
#define M 1003

using namespace std;
int dp[M], val[M], vol[M];

int main()
{
    int n, CAP, v, i, nowv, T;
    sc(T);
    while (T--)
    {
        mem0(dp);
        sc(n);
        sc(CAP);
        sc(val, 1, n+1);
        sc(vol, 1, n+1);
        FD(i, 1, n)
        {
            for(v=CAP,nowv=vol[i]; v>=nowv; v--)
            {
                if (dp[v] < dp[v-nowv]+val[i])
                    dp[v] = dp[v-nowv]+val[i];
                if (i==n) break;
            }
        }
        printf("%d\n", dp[CAP]);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42102584/article/details/81137730