01背包问题 完全背包问题 多重背包问题:
1.1033 采药:
题目大意就是有M种草药可以采摘,每种草药只有一株,且每种草药价值为v,采摘所用时间为t, 现在小明有T(总时间)去采摘草药,问如何才能使采摘到的
草药总价值最大。
这是一个01背包问题
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int max(int x,int y);
int m,n;
int i,j;
int t[101];
int v[101];
int f[1001]={0};
cin>>m>>n; // time number
for(i=1;i<=n;i++)
{
cin>>t[i]>>v[i]; //药时间 药价
}
for(i=n;i>0;i--) //逆序处理
{
for(j=m;j>=t[i];j--)
{
f[j]=max(f[j],f[j-t[i]]+v[i]); //转移方程
}
}
cout<<f[m]<<endl;
return 0;
}
int max(int x,int y)
{
if(x>=y)
return x;
else if(x<y)
return y;
}
类似的问题还有1175 开心的金明
2.1043.采药2;
题目大意与采药基本上一样,主要的区别就是该问题中每种草药的个数是无限多的,即意味着可以只采摘一种草药。
这是一个完全背包问题
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t[1001];
int v[1001];
int f[1001];
int main()
{
int max(int x,int y);
int n,m; // n总重 m总时间
int i,j;
// int t[1001];
// int v[1001];
// int f[1001];
cin>>n>>m;
for(i=1;i<=m;i++)
{
cin>>t[i]>>v[i]; //药重 药价
}
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++)
{
if(t[i]<=j)
{
f[j]=max(f[j],f[j-t[i]]+v[i]); //转移方程
}
}
}
cout<<f[n]<<endl;
return 0;
}
int max(int x,int y)
{
if(x>=y)
return x;
else if(x<y)
return y;
}
相似的题目有1360 DP(为啥不叫卡路里呢)
1061. 采药3
题目大意还是跟上面的差不多,但多了一种限制条件(每种药材质量,背包可承受最大重量),其实只要再加一层for循环就好了
这是一个多重背包问题
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int m,t,n;
int u[1005];
int w1[1005];
int w2[1005];
int v[1005];
int f[1005][1005];
int max(int x,int y)
{
if(x>=y)
return x;
else
return y;
}
int main() //二维费用背包
{
cin>>m>>t>>n;
int i;
for(i=0 ; i<n; i++)
{
cin>>w1[i]>>w2[i]>>v[i];
}
for(int i = 1 ; i <= t ;i++) //表示背包可以不存储满
{
for(int j = 1 ; j <= m ;j++)
{
f[i][j] = 0 ;
}
}
f[0][0]=0;
for( i=0 ; i<n ; i++)
{
for(int T=t ;T>=w2[i]; T--) // 多加了一层for循环
{
for(int M=m ; M>=w1[i]; M--)
{
f[T][M]=max(f[T-w2[i]][M-w1[i]] + v[i] , f[T][M]) ; // 状态转移方程也相应的多了一个参数
}
}
}
cout<<f[t][m]<<endl;
return 0;
}