普通的完全背包我们都会,但是要是背包的容量炒鸡大,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; }