超大完全背包

普通的完全背包我们都会,但是要是背包的容量炒鸡大,dp数组开不下怎么办呢?下面敬上超大完全背包模板一份。

大闹上兰帝国

时间限制: C/C++ 20000ms; Java 40000ms 内存限制: 65535KB

通过次数: 9 总提交次数: 20

问题描述

       由于zbt日常搞事情,早已弄得上兰帝国天翻地覆。于是很快被SHlong列入了上兰帝国重点教育对象,zbt作为一个不受驯服的人当然要奋起反抗了,于是他开始四处破坏,SHlong由于能力有限不能降服zbt,于是只能去ACM实验室请来了声望极高的Wukan方丈,Wukan方丈对zbt说:“听说你十分擅长传说中的背包问题,那么我就出一个完全背包,你若是答得出来就让你随便搞事情。你要是答不出来,那我就要把你赶出上兰帝国了”。zbt当然随口答应了,于是Wukan方丈就开始出题了。

       有一个容量为S的背包,和N种物品,每种物品都有一个体积和价值,每种物品可以无限使用。求容量不超过S的情况下价值的能放入背包的最大价值。

       zbt看了下题嘲讽道:“这不是一道大水题吗”,话音未落,他突然发现貌似存在一些小(很大的)问题。于是他偷偷的使用传音之术来请你帮助他来解决这个问题。


输入描述

输入包含多组数据

每组数据第一行有两个正整数N,S分别代表物品的种类和背包的容量。

后面N行每行两个数v,w代表每种物品的体积和价值。

1<=N,v<=1000;

0<=S,w<=1000000000;


输出描述

对于每组数据分别输出一行,每行只有一个正整数,代表可以放入的最大的价值。


样例输入
3 100
14 5
13 2
5 1
样例输出
35
来源
第三届山西省大学生程序设计大赛

#include <iostream>
#include <cstdio>
#include <cstring>
#define me(x,y) memset(x,y,sizeof(x))
#define sd(x) scanf("%d",&x)
#define ss(x) scanf("%s",x)
#define sf(x) scanf("%f",&x)
#define slf(x) scanf("%lf",&x)
#define slld(x) scanf("%lld",&x)
#define pd(x) printf("%d\n",x)
#define plld(x) printf("%lld\n",x)
#define ps(x) printf("%s\n",x)
#define max(x,y) (x>=y?x:y)
#define min(x,y) (x<y?x:y)
#define sum(x,y) (x+y)
#define INF 0x3f3f3f3f

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=1005;

ll n,c;
ll dp[maxn*5];
ll dp2[55][maxn*5];
ll w[maxn],v[maxn];
ll low[50];

void init() {
    me(dp,0);
    me(dp2,0);
    me(low,0);
}

int main() {
    while(scanf("%lld%lld",&n,&c)!=EOF) {
        ll maxv=0;
        for(int i=1;i<=n;i++) {
            slld(v[i]);
            slld(w[i]);
            maxv=max(maxv,v[i]);
        }
        init();
        ll s=c;
        ll cnt=0;
        while(s>0){
            low[++cnt]=s;
            s=((s-maxv)>>1);
        }
        for(ll i=1;i<=n;i++)
            for(ll j=v[i];j<=maxv*4;j++)
                dp[j]=max(dp[j],dp[j-v[i]]+w[i]);

        for(ll i=cnt;i>=1;i--){
            for(ll j=low[i];j<=low[i]+maxv*2;j++){
                if(j<=4*maxv) dp2[i][j-low[i]]=dp[j];
                else{
                    for(ll k=(j-maxv)/2;k<=j/2;k++)            //下一层
                        dp2[i][j-low[i]]=max(dp2[i][j-low[i]],dp2[i+1][k-low[i+1]]+dp2[i+1][j-k-low[i+1]]);
                }
            }
        }
        plld(dp2[1][0]);
    }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/easylovecsdn/article/details/80215842
今日推荐