01背包:
针对01背包进行的一维数组的优化:
普通的01背包做法是通过开创一个二维数组来记录不同物品不同背包容量下的最大价值进而逐步推导。但是如果题目只要求求出要求的最大价值而不需要输出各种最大价值以及这些最大价值下所装的物品,我们可以对二维数组优化缩小为一维数组dp。
首先观察核心代码:
a[i][j]=max(a[i-1][j],a[i-1][j-q[i].t]+q[i].val);
这段代码运算我们只利用了二维数组前一行的数据进行推断,所以我们可以在遍历一行最大价值后,下一行最大价值直接在当行的最大价值下进行赋值运算。
即:dp[ j ]=max( dp[ j ],dp[ j - q[ i ].weight ]+q[ i ].val );
完整循环代码:
for(int i=1;i<=n;i++){
for(int j=m;j>=0;j--){
if(j>=w[i]){
f[j]=max(f[j],f[j-w[i]]+c[i]);
}
}
}
注意:如果第二层循环的j从第一个元素下标开始而不是最后一个,则后面对最大价值的赋值是基于对当行物品条件的最大价值来赋值的而不是前一行。
贪心:
最大子段和:
给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。
思路:
我们定义一个sum记录前多个元素和,用result来记录最大的sum,a用来记录元素大小,边赋值边做运算。
代码:
scanf ("%lld",&n);
while (n--){
scanf ("%lld",&a);
sum+=a;
if (sum>result) //更新最大的的结果
result=sum;
if (sum<0) //遇到sum<0,那就不可能是最大结果了,直接重启sum从下一个元素开始。
sum=0;
}
printf ("%lld",result); //直接输出最大的结果
这里题目可能要我们考虑元素全是负数的情况,所以对result的初始化需要是一个巨小的负数。
买卖股票时机:
股票[ 7,1,5,10,3,6,4],求出最大利润。
思路:
本体不要求算出哪天买卖以及没有特殊条件,只要求算出买卖最大利润。所以我们可以运用贪心算法。对于股票买卖,利润==卖的钱 - 买的钱。那么既然需要利润最大,我们只需要将正利润相加即可。
对于该数组,我们进行前后作差算出利润先后为:-6,4,5,-7,3,2。
那么我们只需将整数相加便是最大利润为12。
比如,对于第二天买,第四天再卖我们可以得到利润为9,所以4+5是指我们从第二天买再到第四天卖而得到的总利润。
代码:
for(i=1;i<n;i++){
t=a[i]-a[i+1];
if(t>0){
sum+=t;
}
}
printf("%d",sum);