01背包
#include<iostream>
#include<cstring>
using namespace std;
const int N=1010;
int f[N];
int val[N],vol[N];
int main()
{
int T;
cin>>T;
while(T--)
{
int n,V;
cin>>n>>V;
memset(f,0,sizeof(f)); //注意要初始化,否则WA
for(int i=0;i<n;i++)
{
cin>>val[i];
}
for(int i=0;i<n;i++)
{
cin>>vol[i];
}
for(int i=0;i<n;i++)
{
for(int j=V;j>=vol[i];j--)
{
f[j]=max(f[j],f[j-vol[i]]+val[i]);
}
}
cout<<f[V]<<endl;
}
return 0;
}
//本题中将菜的价格看做 背包中的价值 和 体积,即价值与体积相等的情况
//把卡的余额看做 背包的容量
//思路是 把最贵的菜放到最后,在 n-1 之前将余额花到最接近 5元 ,即求接近5元 的最大消费
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1010;
int f[N];
int val[N];
int main()
{
int n;
while(cin>>n,n)
{
memset(f,0,sizeof(f));
for(int i=0;i<n;i++)
{
cin>>val[i];
}
sort(val,val+n);//排序将最贵的菜放到最后
int m;
cin>>m;
int V=m-5; //最大容量就是可以花到的最大金额,使得余额最接近 5 元
if(m<5) //如果余额已经小于 5 元,则输出
{
cout<<m<<endl;
continue;
}
for(int i=0;i<n-1;i++) //前 n-1 个菜
{
for(int j=V;j>=val[i];j--)
{
f[j]=max(f[j],f[j-val[i]]+val[i]);
}
}
cout<<m-f[V]-val[n-1]<<endl; //余额减去最大消费,减去最贵的菜价格
}
return 0;
}
完全背包
HDU 1114
小猪存钱罐装满的重量减去空时的重量,为 小猪存钱罐的容量v=F-E , 应用完全背包的知识求得最少的硬币。
#include<iostream>
using namespace std;
const int N=10010;
const int INF = 1e9;
int f[N];
int val[N],weight[N];
int main()
{
int T;
cin>>T;
while(T--)
{
int E,F;
int v,n;
cin>>E>>F;
v=F-E;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>val[i]>>weight[i];
}
//一定要注意初始化
fill(f,f+10010,INF);
f[0]=0;
int MAx=INF;
for(int i=0;i<n;i++)
{
for(int j=weight[i];j<=v;j++)
{
f[j]=min(f[j],f[j-weight[i]]+val[i]);
}
}
//注意判断条件
if(f[v]>=INF)
{
cout<<"This is impossible."<<endl;
}
else
{
cout<<"The minimum amount of money in the piggy-bank is "<<f[v]<<"."<<endl;
}
}
return 0;
}
HDU 2159
本题说每种怪都有无数个,所以可以看做完全背包问题。其中要考虑忍耐度和杀怪数量两个因素,所求的的经验值要 > n ,所以要开一个二维数组 j 表示忍耐值 k 表示杀怪数量(注意循环中的顺序)
#include<iostream>
#include<cstring>
using namespace std;
const int N=105;
const int INF=1e9;
int f[N][N];
int val[N],w[N];
int main()
{
int n,m,k,s;
while(cin>>n>>m>>k>>s)
{
for(int i=0;i<k;i++)
{
cin>>val[i]>>w[i];
}
int ren=INF;
memset(f,0,sizeof(f));
for(int i=0;i<k;i++)
{
for( int j=w[i];j<=m;j++)
{
for(int k=s-1;k>=0;k--)
{
f[j][k]=max(f[j][k],f[j-w[i]][k+1]+val[i]);
if(f[j][k]>=n&&j<ren) ren=j;
}
}
}
//注意判断条件
if(ren< INF)
{
cout<<m-ren<<endl;
}
else
{
cout<<"-1"<<endl;
}
}
}
多重背包
#include <cstring>
#include <algorithm>
// 多重背包求得最大价值
#include <iostream>
#include<cmath>
using namespace std;
const int N = 10010;
int v[110], w[110], num[110];
//多重背包:v表示价值,w表示空间,num表示个数
int val[1010], weight[1010];
//01背包:val表示新的价值,weight表示新的空间
int dp[N];
int main() {
int T;
cin>>T;
while(T--)
{ int n,m;
cin>>m>>n;
int count = 0;
for(int i = 0; i < n; i++)
{
cin>>v[i]>>w[i]>>num[i];
for(int j = 1; j <= num[i]; j << 1) {
val[count] = j * v[i];
weight[count++] = j * w[i];
num[i] -= j;
}
if(num[i] > 0) {
val[count] = num[i] * v[i];
weight[count++] = num[i] * w[i];
}
}
memset(dp, 0, sizeof(dp));
for(int i = 0; i < count; i++) {
for(int j = m; j >= val[i]; j--) {
dp[j] = max(dp[j], dp[j - val[i]] + weight[i]);
}
}
cout<<dp[m]<<endl;
}
return 0;
}