背包
来源:互联网 发布:魔力怀旧宠物满档数据 编辑:程序博客网 时间:2024/04/29 17:57
@JintianGo
2014-11-08 10:44
字数 2396
阅读 1
模板
背包
- 背包
- 一.01背包:(每种背包零或一)
- 二.完全背包:(每种数量不限)
- 三.多重背包:(每种背包数量给出)
- 四.完整程序
- 五.例题
- 1(POJ1276)
- 2(UVA12653)
- 背包
一.01背包:(每种背包零或一)
int v; //v为总的容量
int dp[N];
void ZeroOnePack(int cost,int weight){
for(int j=v;j>=cost;j--) ///注意是逆序的(滚动数组)
dp[j]=max(dp[j],dp[j-cost]+weight);
}
二.完全背包:(每种数量不限)
int v; //v为总的容量
int dp[N];
void CompletePack(int cost,int weight){
for(int j=cost;j<=v;j++) ///注意是顺序的
dp[j]=max(dp[j],dp[j-cost]+weight);
}
三.多重背包:(每种背包数量给出)
何谓多重背包,就是在原来经典的0/1背包的基础上规定一个物品可以背有限次,也是区别于无限背包的特点之一。其实解决的方法很简单,只要把一个物品的多次看做是另一个物品,也就是说产生一种新的物品这个物品的重量是原来的两倍,三倍,…n倍。这样就将多重背包转化成了典型的0/1背包了.
int v; //v为总的容量
int dp[N];
void MultiplePack(int cost,int weight,int amount){
if(cost*amount>=v)
CompletePack(cost,weight);
else
{
int k=1;
while(k<amount)
{
ZeroOnePack(k*cost,k*weight);
amount-=k;
k+=k;
}
ZeroOnePack(amount*cost,amount*weight);
}
}
四.完整程序
void ZeroOnePack(int cost,int weight)
{
for(int j=v; j>=cost; j--) ///注意是逆序的
dp[j]=max(dp[j],dp[j-cost]+weight);
}
void CompletePack(int cost,int weight)
{
for(int j=cost; j<=v; j++) ///注意是顺序的
dp[j]=max(dp[j],dp[j-cost]+weight);
}
void MultiplePack(int cost,int weight,int amount)
{
if(cost*amount>=v)
CompletePack(cost,weight);
else
{
int k=1;
while(k<amount)
{
ZeroOnePack(k*cost,k*weight);
amount-=k;
k+=k;
}
ZeroOnePack(amount*cost,amount*weight);
}
}
五.例题
1(POJ1276)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <stack>
#define maxn 100000+10
using namespace std;
int v,N;
int cnt[11],c[1001];
int dp[maxn];
void ZeroOnePack(int cost,int weight)
{
for(int j=v; j>=cost; j--) ///注意是逆序的
dp[j]=max(dp[j],dp[j-cost]+weight);
}
void CompletePack(int cost,int weight)
{
for(int j=cost; j<=v; j++) ///注意是顺序的
dp[j]=max(dp[j],dp[j-cost]+weight);
}
void MultiplePack(int cost,int weight,int amount)
{
if(cost*amount>=v)
CompletePack(cost,weight);
else
{
int k=1;
while(k<amount)
{
ZeroOnePack(k*cost,k*weight);
amount-=k;
k+=k;
}
ZeroOnePack(amount*cost,amount*weight);
}
}
int main()
{
while(~scanf("%d%d",&v,&N))
{
for(int i=0; i<N; i++)
cin>>cnt[i]>>c[i];
memset(dp,0,sizeof(dp));
for(int i=0; i<N; i++)
MultiplePack(c[i],c[i],cnt[i]);//注意这里要考虑到起点的cost与weight都是c[i]
cout<<dp[v]<<endl;
}
return 0;
}
2(UVA12653)
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 10000
using namespace std;
int a[55];
int dp[maxn];
int main()
{
int T,n,t;
cin>>T;
int tmp=T;
while(T--)
{
cin>>n>>t;
memset(dp,-1,sizeof(dp));
dp[0]=0;
for(int i=0;i<n;i++)
{
cin>>a[i];
for(int j=t-1;j>=a[i];j--)
if(~dp[j-a[i]])//一个小优化
dp[j]=max(dp[j],dp[j-a[i]]+1);
}
int ans=0,index=0;
for(int j=t-1;j>=0;j--)
{
if(dp[j]>ans)
{
ans=dp[j];
index=j;
}
}
printf("Case %d: %d %d\n",tmp-T,ans+1,index+678);
}
}
@JintianGo
2014-11-08 10:44
字数 2396
阅读 1
正在加载文章图片,请稍等片刻...
0 0