蒟蒻水的第一发博客,被一个模板题折磨了一下午(笑)
洛谷 P1060
代码如下:
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int chengji[100000000], jiage[30], jiazhi[30]; int n, m;//n为钱数,m为个数 int main(void){ cin>>n>>m; for(int i=0; i<m; i++){ cin>>jiage[i]>>jiazhi[i]; jiazhi[i]=jiage[i]*jiazhi[i]; } for(int i=0; i<m; i++){ for(int j=n; j>=jiage[i]; j--){ chengji[j]=max(chengji[j],chengji[j-jiage[i]]+jiazhi[i]); } } cout<<chengji[n]; return 0; }
此为优化后的一维数组,为方便理解,再贴一份二维数组(来自洛谷题解)
#include <iostream> using namespace std; int f[30][100000]; int w[10000]; int v[10000]; int main() { int n,m; int i,j,k; cin>>m>>n; //提前相乘 for(i=1;i<=n;i++) { cin>>w[i]>>v[i]; v[i]*=w[i]; } for(int i=1;i<=n;i++) { //01背包最关键的位置,为防止反复加同一物品,需要倒着搜,这也是01背包与完全背包的不同之处 for(int c=0;c<=m;c++) { f[i][c]=f[i-1][c]; if(c>=w[i]) f[i][c]=max(f[i][c],f[i-1][c-w[i]]+v[i]); } } cout<<f[n][m]; return 0; }
一维数组和二维数组两种思路均为当最后一个物品序号位i时(1<=i<=m)如何能使乘积取最大值,不同点在于起始点的不同。
二维数组的思路为在以序号为i的物体为最后一个时,计算剩余体积为j(0<=j<=n)时能取到的最大乘积,
一维数组的思路为假定将第i个物品放入背包,剩余如何取能取到最大。
一开始想用递归方法做出,但是找不到限制背包空间的表达式,因此做罢。
立一个2020年的flag,把这道题用递归方法再做一遍XD