骨骼收集器01背包

来源hdu2602

问题描述

许多年前,在泰迪的家乡,有一个人被称为“骨头收藏家”。这个男人喜欢收集各种各样的骨头,比如狗狗,牛,还有他去了坟墓......
骨头收藏家有一个大容量的V袋,沿着他的收集之旅有很多骨头,显然,不同的骨骼具有不同的值和不同的体积,现在根据他的行程给出每个骨骼的值,你能计算出骨骼采集器可以得到的总值的最大值吗?

1329647-20180816152726681-530226180.png

输入

第一行包含整数T,个案数。
接下来是T个案例,每个案例有三行,第一行包含两个整数N,V,(N <= 1000,V <= 1000)表示骨骼的数量和他的包的体积。第二行包含表示每个骨骼值的N个整数。第三行包含表示每个骨骼体积的N个整数。

输出

每行一个整数表示总值的最大值(此数字将小于2 31)。

样本输入

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

样本输出

14

最基础01背包,判断第i件要不要放进去,状态转移方程dp[i][V]=max{dp[i-1][V],dp[i-1][V-v[i]]+w[i]}

“将前i件物品放入容量为v的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”;如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的容量为v-c[i]的背包中”,此时能获得的最大价值就是f [i-1][v-c[i]]再加上通过放入第i件物品获得的价值w[i]。

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include <iomanip>
#include<cmath>
#include<float.h> 
#include<string.h>
#include<algorithm>
#define sf scanf
#define pf printf
#define scf(x) scanf("%d",&x)
#define scff(x,y) scanf("%d%d",&x,&y)
#define prf(x) printf("%d\n",x) 
#define mm(x,b) memset((x),(b),sizeof(x))
#include<vector>
#include<queue>
#include<map>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
typedef long long ll;
const ll mod=1e9+100;
const double eps=1e-8;
using namespace std;
const double pi=acos(-1.0);
const int N=1005;
int dp[N][N];
int w[N],v[N];
int main()
{
    int re,V,n;
    scf(re);
    v[0]=0;w[0]=0;
    while(re--)
    {
        mm(dp,INT_MIN);
        scff(n,V);
        rep(i,1,n+1)
            scf(w[i]);
        rep(i,1,n+1)
            scf(v[i]);
        rep(i,1,n+1)//第i件物品 
            rep(j,0,V)//空间为j的时候 
            {
                if(v[i]<=j)
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-v[i]]+w[i]);
                else
                dp[i][j]=dp[i-1][j];
            }
        prf(dp[n][V]);
    }
    return 0;
}

一维

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include <iomanip>
#include<cmath>
#include<float.h> 
#include<string.h>
#include<algorithm>
#define sf scanf
#define pf printf
#define scf(x) scanf("%d",&x)
#define scff(x,y) scanf("%d%d",&x,&y)
#define prf(x) printf("%d\n",x) 
#define mm(x,b) memset((x),(b),sizeof(x))
#include<vector>
#include<queue>
#include<map>
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
typedef long long ll;
const ll mod=1e9+100;
const double eps=1e-8;
using namespace std;
const double pi=acos(-1.0);
const int N=1e3+5;
int dp[N];
int w[N],v[N];
int main()
{
    int re,V,n;
    scf(re);
    while(re--)
    {
        mm(dp,0);
        scff(n,V);
        rep(i,1,n+1)
            scf(w[i]);
        rep(i,1,n+1)
            scf(v[i]);
        rep(i,1,n+1)
        {
            per(j,V,v[i])
                dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
        }
        prf(dp[V]);
    }
    return 0;
}

转载于:https://www.cnblogs.com/wzl19981116/p/9487625.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值