模板
/**
* 多重背包:
* 有N种物品和一个容量为 V的背包。第i种物品最多有 num[i]件可用,
* 每件耗费的空间是C[i],价值是W[i]。
* 求解将哪些物品装入背包可使这些物品的耗费的空间总和不超过背包容量,且价值总和最大。
*/
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 100005
int c[maxn], w[maxn], num[maxn];//c:费用 w:价值 num:数量
int dp[maxn]; //当前位置符合题意的最优解
int V; //V:总容量
//01背包
void ZeroOnePack(int c, int w)
{
for (int v = V; v >= c; v--)
{
dp[v] = max(dp[v], dp[v - c] + w);
}
}
//完全背包
void CompletePack(int c, int w)
{
for (int v = c; v <= V; v++)
{
dp[v] = max(dp[v], dp[v - c] + w);
}
}
//多重背包
void MultiplePack(int c, int w, int num)
{
if (c * num >= V)
{
CompletePack(c, w);
}
else
{
int k = 1;
while (k < num)
{
ZeroOnePack(k*c, k*w);
num -= k;
k <<= 1;
}
ZeroOnePack(num*c, num*w);
}
}
int main()
{
int t;
cin>>t
while (t--)
{
int n;
scanf("%d%d", &V, &n);
for (int i = 1; i <= n; i++)
cin>>c[i]>>w[i]>>num[i];
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)
MultiplePack(c[i], w[i], num[i]);
cout<<dp[V];
}
return 0;
}
01 背包:
/*
01背包问题
01背包问题的特点是,每种物品仅有一件,可以选择放或不放。
01背包问题描述:
有N件物品和一个容量为 V的背包。第i件物品的重量是w[i],价值是v[i]。
求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
poj 3624
*/
#include<iostream>
#define N 1000005
#include<algorithm>
#include<cstring>
using namespace std;
int w[N],v[N],dp[N];
int main()
{
int i, j, n, m;
while(cin>>n) //n件物品
{
cin>>m;//容积为m
memset(dp,0,sizeof(dp));
for(i=0; i<n; i++)
cin>>w[i]>>v[i];//w[i]为重量,v[i]为价值
for(i=0; i<n; i++)
{
for(j=m; j>=w[i]; j--) //选与不选两条途径
dp[j] = max(dp[j], dp[j-w[i]]+v[i]);
}
cout<<dp[m];
}
return 0;
}
完全背包:
/*
完全背包问题的特点是,每种物品可以无限制的重复使用,可以选择放或不放。
完全背包问题描述:
有N物品和一个容量为 V的背包。第i件物品的重量是w[i],价值是v[i]。
//此代码为HDU1114;
*/
#include <iostream>
#include <algorithm>
#define INF 0x3fffffff
#define N 10047
using namespace std;
int dp[N],v[N],w[N];
int main()
{
int t,i,j,k,e,f,m,n;
cin>>t;
while(t--)
{
cin>>e>>f;
int c = f-e;
for(i = 0 ; i <= c ; i++)
dp[i]=INF;
cin>>n;
for(i = 0 ; i < n ; i++)
{
cin>>v[i]>>w[i];//v[i]为价值,w[i]为重量
}
dp[0]=0;
//注意初始化(要求恰好装满背包,那么在初始化时除了dp[0]为0其它f[1..V]均设为求最大(-∞),最小(∞)
//这样就可以保证最终得到的dp 是一种恰好装满背包的最优解。
//如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将f[0..V]全部设为0)
for(i =0 ; i < n ; i++) //n为物品种类数
{
for(j = w[i] ; j <= c ; j++) //c为最大容积
{
dp[j] = min(dp[j],dp[j-w[i]]+v[i]);//此处求的是最坏的情况所以用min,确定最少的钱
}
}
if(dp[c] == INF)
printf("This is impossible.\n");
else
printf("The minimum amount of money in the piggy-bank is %d.\n",dp[c]);
}
return 0;
}
多重背包:
//多重背包(MultiplePack): 有N种物品和一个容量为 V的背包。
//第i种物品最多有num[i]件可用,每件费用是pre[i],价值是w[i]。
//求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,
//且价值总和最大。
//hdu 2191
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 1005
using namespace std;
int main()
{
int t,n,m,i,j,k;
int w[N],pri[N],num[N],dp[N];//dp存的是当前符合题意最大价值,pre[i]所需容积,w[i]价值;
while(cin>>t)
{
while(t--)
{
memset(dp,0,sizeof(dp));
cin>>n>>m;//n为总金额,m为大米种类
for(i = 0 ; i < m ; i++) //m种类总数
{
cin>>pri[i]>>w[i]>>num[i];//num[i]为每种物品的数量,pre[i]所需容积,w[i]价值
}
for(i = 0 ; i < m ; i++) // m为总种类数
{
for(j = 0 ; j < num[i] ; j++) //num[i]为每种物品的数量,
{
for(k = n ; k >= pri[i]; k--) //pre[i]所需容积
{
dp[k] = max(dp[k],dp[k-pri[i]]+w[i]);
}
}
}
cout<<dp[n]<<endl;
}
}
return 0;
}