经典问题: 有n个物品,分别价值为value,重为volume, 放入一个m的背包 (保证放满) 问如何使得价值最大
分析: 首先从最后那个状态来看 dp[i][j]=max(dp[i-1],dp[i-1][ j-vo[i] ]+va[i]),起始状态显然是dp[0][j]=0,有了起始状态 我们便可以一次一次的转移到最后的最大值
对于一些细节上的解释:枚举j(重量)时有些j 并不会用到,也不会产生影响(遇到两个重复出现时,会取最大的),因为各个情况都要考虑到所以每个j都考虑,也有可能数据太大了此时就需要离散化 ,只枚举必须的部分。
因为状态转移是根据i转(j两两之间没有关系)而i 也就这个用前一个 在往后推 最前面的就用不着了所以可以用滚动数组滚去一个维度,比如斐波那契数列。 同时j从高向低走保证不会刷新后面要用到的数
初始状态和末状态都可以 由i去判定
ac代码:
#include<bits/stdc++.h> using namespace std; struct node { int vo,va; }bone[1002]; int dp[1002]; int main(){ ios::sync_with_stdio(0); cin.tie(0); int t; cin>>t; while(t--){ int n,m; cin>>n>>m; for(int i=0;i<n;i++) cin>>bone[i].va; for(int i=0;i<n;i++) cin>>bone[i].vo; for(int i=0;i<=m;i++) dp[i]=0; for(int i=0;i<n;i++) for(int j=m;j>=bone[i].vo;j--) dp[j]=max(dp[j],dp[j-bone[i].vo]+bone[i].va); cout<<dp[m]<<endl; } }