动态规划是一种解决问题的思想。动态规划最关键的问题在于找到子问题模型。
比如递归,递归会不停的调用同一段代码,自顶而下,类似于树结构,当然,结果还是依赖出口,再层层由下层返回到上层。但是我们说,这种解决问题的思想就是DP的自顶向下思想。
比如迭代,for循环。这个子问题的结果作为下一个子问题的初始条件,直到计算出最终结果。这种由小到大的就是DP的自下而上思想。
找到子问题,再将子问题抽象为数学公式,这个公式就是状态转移方程。
一般来讲找到状态转移方程以后,同样的问题,利用DP思想就有两种解法,一种是自顶而上的解法,一种就是自下而上的解法。这两种解法无论是哪一种,在解决子问题的时候都会出现重复子问题的现象。因此,可以做一个缓存,从而降低时间复杂度。
公式
(1 )FB(n)=FB(n-1)+FB(n-2);n>2
(2)F(n)=1;n==1 || n==2
调用代码:
int r= FB2(7);
printf("%d \n",r);
DP自顶向下如下解:
int FB(int n){
if (n==1 || n==2) {
return 1;
}
return FB(n-1)+FB(n-2);
}
DP自下而上如下解:
//动态规划
int FB1(int n){
if (n==1 || n==2) {
return 1;
}
//创建一维数组缓存结果。
int arr[n+1];
memset(arr, n, sizeof(int)*(n+1));
arr[0]=arr[1]=1;
for (int i=2; i<n; i++) {
arr[i]=arr[i-1]+arr[i-2];
}
return arr[n-1];
}
DP自下而上如下解优化
//动态规划优化
int FB2(int n){
if (n==1 || n==2) {
return 1;
}
int a=1,b=1;
int c=0;
for (int i=2; i<n; i++) {
c=a+b;
a=b;
b=c;
}
return c;
}
空间复杂度最终被优化为O(1);
0-1背包问题
我们有n种物品,物品j的重量为wj,价格为pj。
我们假定所有物品的重量和价格都是非负的。背包所能承受的最大重量为W。
如果限定每种物品只能选择0个或1个,则问题称为0-1背包问题 。
子问题分析->状态转移方程。
1 如果一件物品放入背包,超过了剩余空间。那么 max = bagValues(index - 1, limitWeight);
2 // 如果选择此时的重量最大值
int selectValue = curValue + bagValues(index - 1, limitWeight - curWeight);
// 如果跳过此时的重量最大值
int skipValue = bagValues(index - 1, limitWeight);
max = MAX(selectValue, skipValue);
3 代码实现
/**
输入:
int Values[n] 物品的价值
int Weights[n] 物品的重量
int LimitWeight 背包容量剩余大小
输出:
MaxValue 背包里的物品最大价值
状态:取:最大价值(取)/不是最大价值(取过之后)
不取:重量超出限制
物品重量不得超过最大重量限制
*/
int *values;
int *weights;
int bagValues(int index, int limitWeight) {
if(limitWeight <= 0 || index < 0 ){
return 0;
}
int max = 0;
// 当前物品重量
int curWeight = weights[index];
// 当前物品价值
int curValue = values[index];
if (curWeight > limitWeight) {
// 超过重量限制,跳过
max = bagValues(index - 1, limitWeight);
} else {
// 如果选择此时的重量最大值
int selectValue = curValue + bagValues(index - 1, limitWeight - curWeight);
// 如果跳过此时的重量最大值
int skipValue = bagValues(index - 1, limitWeight);
max = MAX(selectValue, skipValue);
}
return max;
}
调用部分:
int main(int argc, const char * argv[]) {
int vs[] = {4, 10, 17};
int ws[] = {1, 2, 3};
values = vs;
weights = ws;
int m = bagValues(1, 5);
printf("%d \n",m);
return 0;
}