动态规划

动态规划:
(1)将大问题变为小问题,大问题的解决依赖小问题的答案,但集合间重合。这一点比较像分治算法,不过分治算法的各个区间互相独立,递归深度遍历时间复杂度(log2n)。
(2)先找出小问题的最优子集,继而找出大问题的最优子集 。这一点像回溯算法子集树,子集树也是寻找最优子集,不过子集树是通过递归,穷举出所有情况(2^n)然后再判断(虽然也有剪枝操作)。
(3)分析问题的方式:a.可以从上往下分析问题(大问题的解决依赖小问题的答案);也可以从下往上分析(归纳总结),得出公式f(n)=C1*f(n-1)+C2*f(n-2);后一点比较像贪心算法,因为贪心总结出的规律一般是发f(n) = C1*n^2+C2*n+C3。

总之,动态规划,适用范围比贪心广,空间复杂度比子集树低,相应的问题分治根本解决不了。那么,我们来总结一下动态规划的题集,主要关注动态规划的核心——辅助数组dp[]。

一. 01背包

有n个物品的重量是w[] = { 8,6,5,4,7 },相应的价值为v[] = { 6,9,7,8,2 },现有容纳重量为18的背包,那么它的最优价值选择是什么?(注:此题也可以用子集树来做)

  1. 辅助数组如何选择?
    直接揭晓答案dp[18+1][5]。它是二维的,一维表示背包容量,一维表示可供选择的集合大小。举例dp[10][3]就表示背包容量为10,从前三项中选择出最优解。
  2. dp如何表示?
    答案是dp[i][j] = max{dp[i][j-1], v[j]+dp[i-w[j]][j-1]}。我们认为dp[i][j-1]的值是,容量为i,前j-1项中选出的最优解,那么现在新加入第j项结果会如何?结果想要改变,那么最优解中就必须包括v[j],不然,岂不是和前j-1项的结果一样了,然后两种情况进行比较,谁价值大选谁。
  3. 代码
int main()
{
	int w[] = { 8,6,5,4,7 };
	int v[] = { 6,9,7,8,2 };
	const int n = 5;
	const int c = 18;

	int dp[c + 1][n] = { 0 };
	for (int i = 0; i <= c; ++i)
	{
		if (i >= w[0])
		{
			dp[i][0] = v[0];
		}
	}

	for (int i = 1; i <= c; ++i)
	{
		for (int j = 1; j < n; ++j)
		{
			int tmp = 0;
			if (i >= w[j])
			{
				tmp = v[j] + dp[i - w[j]][j - 1];
			}
			dp[i][j] = tmp > dp[i][j - 1] ? tmp : dp[i][j - 1];
		}
	}

	cout << dp[c][n-1] << endl;
	return 0;
}

二、两个字符串的重复子串和重复子序列

有字符串str1 = "helloworld"和str2 = “owoyuld”,求他们两者间重复的字串和子序列(注:字序列是可以不连续,而字串必须连续,且字串也可以用栈来做)

  1. 辅助数组的建立?
    这里肯定是dp[m][n],一个字符串一维。
  2. 推到dp[x][y]等式
    字串:dp[x][y] = str[x] == str[y] ? dp[x-1][y-1]+1 : 0
    子序列: dp[x][y] = str[x] == str[y] ? dp[x-1][y-1]+1 : max{dp[x-1][y], dp[x][j-1]}
  3. 代码
//字串
int LCS1(string str1, int m, string str2, int n, int **dp)
{
	int maxVal = 0;
	for (int i = 0; i < m; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			if (str1[i] == str2[j])
			{
				dp[i + 1][j + 1] = dp[i][j] + 1;

				if (maxVal < dp[i + 1][j + 1])
				{
					maxVal = dp[i + 1][j + 1];
				}
			}			
		}
	}
	return maxVal;
}
//子序列
int LCS2(string str1, int m, string str2, int n, int **dp)
{
	int maxVal = 0;

	dp[0][0] = 0;

	for(int i=1; i<m; ++i)
	{
		dp[i][0] = dp[i-1][0];
		if(str1[i] == str2[0])
		{
			dp[i][0] += 1;
		}
	}

	for(int j=1; j<n; ++j)
	{
		dp[0][j] = dp[0][j-1];
		if(str2[j] == str1[0])
		{
			dp[0][j] += 1;
		}
	}

	for (int i = 1; i < m; ++i)
	{
		for (int j = 1; j < n; ++j)
		{
			if (str1[i] == str2[j])
			{
				dp[i][j] = dp[i-1][j-1] + 1;
			}
			else
			{
				if (dp[i][j-1] > dp[i-1][j]) 
				{
					dp[i][j] = dp[i][j-1];
				}
				else
				{
					dp[i][j] = dp[i-1][j];
				}
			}
		}
	}

	return dp[m-1][n-1];
}
  1. 子序列图
    在这里插入图片描述
期末大作业基于python的足球运动员数据分析源码+数据集(高分项目),个人经导师指导并认可通过的高分设计项目,评审分98分,项目中的源码都是经过本地编译过可运行的,都经过严格调试,确保可以运行!主要针对计算机相关专业的正在做大作业、毕业设计的学生和需要项目实战练习的学习者,资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于pyth
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值