动态规划:记录结果再利用的 “动态规划”

记录结果再利用的 “动态规划”

斐波那契数列问题

#include <iostream>
#include <vector>
#include <algorithm>
#define MAX_N 2147483647
using namespace std;
//斐波那契数列 fib(n)在展开时  同样的n被调用了多次(fib(9)+fib(8)  展开的同时都调用了fib(7)),我们可以利用数列保存的方式优化其递归

int fib(int n)
{
	if(n<=1) return n;
	return fib(n-1)+fib(n-2);
}

/*优化原理:
 *利用记忆法,将斐波那契数列的已经求出的项进行保存到数组中,之后进行递归
 * 如果memo[n]这一项的值不等于0,我们可以直接返回,表示该值已经被求出。
 * 如果memo[n]等于0,表示该值未被求出,我们就可以利用递归求出该解并存入数组中(作为记忆化保存),之后返回即可。
*/

int memo[MAX_N];
int optimize_fib(int n)
{
	if(n<=1) return n;
    if(memo[n]!=0) return memo[n];
	return memo[n]=optimize_fib(n-1)+optimize_fib(n-2);
}

01背包问题

题目:有n 个重量和价值分别为 wi,vi的物品,从这些物品中挑选总重量不超过 W 的物品,求所有挑选方案中价值总和的最大值。


const vector<pair<int,int>> thingVec{{2,3},{1,2},{3,4},{2,2}};
const int N=4;
const int W=5;

//从第i个物品开始挑选总重小于j的部分
int rec(int i,int j){
	int res;
	if (i==thingVec.size()){
		//已经没有剩余物品了
		res=0;
	}else if (j < thingVec.at(i).first){
		//无法挑选这个物品
		res = rec(i+1 , j);
	} else{
		//挑选和不挑选的两种情况都尝试一下
		res = max(rec(i+1,j), rec(i+1 , j - thingVec.at(i).first)+thingVec.at(i).second);
	}
	return  res;
}


//通过记忆化数组,记录function的两个参数,对递归时重复的部分进行了记录和直接返回,降低了时间复杂度

int dp[N+1][W+1];
int rec_DP(int i,int j){
	if(dp[i][j] >=0 ) return dp[i][j];   //已经计算过的话直接使用之前的结果

	int res;
	if(i==N){
		res=0;
	}else if(j < thingVec.at(i).first){
		res = rec(i+1,j);
	} else{
		res = max(rec(i+1,j),rec(i+1,j)+thingVec.at(i).second);
	}
	//将结果保存在数组中
	return dp[i][j]=res;
}

int main()
{
	memset(dp,-1, sizeof(dp));
	cout<<rec(0,W);
}

注意: 虽然memset按照1字节为单位对内存进行填充,-1 的每一位二进制位都是 1,

const vector<pair<int,int>> thingVec{{2,3},{1,2},{3,4},{2,2}};
const int N=4;
const int W=5;
int dp[N+1][W+1];


//不写递推公式,简单利用 递推式将各项的值计算出来,使用二重循环也可以解决这一类问题,这便叫做DP。
void solve(){

	for (int i = N-1; i>=0; --i) {
		for (int j = 0; j <= W; ++j) {
			if(j < thingVec.at(i).first){
				dp[i][j] = dp[i+1][j];
			}else{
				dp[i][j] = max(dp[i+1][j],dp[i+1][j-thingVec.at(i).first] + thingVec.at(i).second);
			}
		}
	}
	printf("%d\n",dp[0][W]);
}

猜你喜欢

转载自blog.csdn.net/chongzi_daima/article/details/104529423
今日推荐