题目链接
题意:在01背包的基础上多了每个物品都可以无限取的条件
思路:首先考虑在01背包的基础上的暴力枚举,我们可以在枚举前i件物品最多拿j的容量时再遍历当前物品拿的数量
贴一个暴力tle代码:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define INF 0x3f3f3f3f
#define pb push_back
#define int long long
#define Mirai ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
typedef pair<int,int> pii;
const int N=1010;
int dp[N][N];
int n,m,v,w;
void solve()
{cin>>n>>m;for(int i=1;i<=n;i++)//枚举拿前i件物品{cin>>v>>w;for(int j=0;j<=m;j++)//枚举最大容量{for(int k=0;k*v<=j;k++)//枚举每一个物品拿多少个{dp[i][j]=max(dp[i][j],dp[i-1][j-k*v]+k*w);//此处有k=0的情况,dp[i][j]会首先等于dp[i-1][j]}}}cout<<dp[n][m]<<endl;
}
signed main()
{Mirai;int T=1;//cin>>T;while(T--){solve();}
}
所以不难发现dp[i][j]中取max的第二项之后的部分都可以转化为dp[i][j-v]+w
所以可得状态转移方程:
而此时我们同样发现每一层的状态只与i-1层的状态有关,所以仍然可以用01背包的降维优化方式,注意此时需要的状态是更新之后j的左值,所以需要从左往右遍历,而注意如果当前容量不足以装下当前物品,仍然是不需要更新的,所以枚举范围为v[i]~m
ac代码:
#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define INF 0x3f3f3f3f
#define pb push_back
#define int long long
#define Mirai ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
typedef pair<int,int> pii;
const int N=1010;
int n,m,v,w;
int dp[N];
void solve()
{cin>>n>>m;for(int i=1;i<=n;i++){cin>>v>>w;for(int j=v;j<=m;j++){dp[j]=max(dp[j],dp[j-v]+w);}}cout<<dp[m]<<endl;
}
signed main()
{Mirai;int T=1;//cin>>T;while(T--){solve();}
}