动态规划之线性DP

        亲爱的同学们,恭喜你们!你们已经越过C++第一道坎-递归,现在你们迎来的是动态规划——第二道坎。

我们刚刚学的贪心是为线性DP做铺垫的,但是贪心有一个缺点,就是不可以做到全面最优,但DP可以做到。

        动态规划,由前一轮状态退出当前一轮的最优值,这是要记住的。

        版权所有,翻露必究!!!

问题A 探索数字迷塔

Description

晶晶最近迷上了数字迷宫游戏,整天沉浸在一串串看似简单的数字中自得其乐。数字迷宫游戏的魅力体现在变化中隐含着不变的规律,归纳是探究数字迷宫的法宝之一。如图所示,就是一个由线连接起来的数字小方格组成的数字迷塔。

这个迷塔共 n 层,它由 n ×(n + 1)/ 2 个小方格组成。每个小方格中都有一个数字,并且连着下一层的两个小方格。现从塔顶走到塔底,每一步只能走到相邻的方格中,则经过方格的数字之和最大值是多少?这个问题晶晶已经琢磨一天了,她感觉异常棘手。你能帮帮她吗?

Format

Input

输入数据共 n + 1 行,第 1 行是一个整数 n(1 ≤ n ≤ 1000),表示数字迷塔的高度,接下来用 n 行数字表示数字迷塔,其中第 i 行有 i 个正整数,且所有的正整数均不大于 100。

Output

输出可能得到的最大和。

Samples

Sample Input 1

5
9
12 15
10 6 8
2 18 9 5
19 7 10 4 16

Sample Output 1

59

Explanation

样例一说明:

9 → 12 → 10 → 18 → 10

        如果以贪心思想来做,就要考虑到当前最优,那么我们就会9+15+8+9+10,很明显,不是这样的!那么,我们就要考虑全部最优,到两线相交点时,就要打擂台。

阶段-->数字宝塔每一层

状态-->数字宝塔每一层的每一个数

把每个阶段转为下一个阶段时 如何转变的式子-->动态转移方程

本质:枚举(数组记录)

#include<bits/stdc++.h>
using namespace std;
int n,a[1005][1005],dp[1005][1005];
int main() 
{ 	
	cin>>n; 	
	for(int i=1;i<=n;i++) 		
	{
		for(int j=1;j<=i;j++)
		{
			cin>>a[i][j];
		} 
	}
	for(int i=1;i<=n;i++) 		
	{
		dp[n][i]=a[n][i];
	} 
	for(int i=n;i>=1;i--) 	
	{
		for(int j=1;j<i;j++)
		{
			dp[i-1][j]=max(dp[i][j],dp[i][j+1])+a[i-1][j];
		}
	}	
	cout<<dp[1][1];
	return 0;
}

问题B 探索数字迷塔

Description

圣诞特别礼物挂在一棵圣诞树上,这棵树有 n 层,每层有一件礼物,每件礼物都有一个价值,有的礼物还有一些连接线,与下层的礼物相连,领取礼物的规则如下:任选一件礼物,它的下面如果有连接线,则可以继续取它连接的礼物,以此类推,直至取到没有连接线的礼物才结束,你如果是第一个去取,怎样取才能获得最大的价值呢?请你编写一程序解决这一问题。

Format

Input

第一行只有一个数据 n(n ≤ 100),表示有 n 层礼物;

以下有 n 行数据,分别表示第 1 至第 n 层礼物的状态,每行至少由一个数据构成,且第一个数据表示该礼物的价值,后面的数据表示它与哪些层的礼物相连,如果每行只有一个数据则说明这层礼物没有与下层礼物相连,每个数的大小均不超过 10000。

Output

只有一个数,表示获得的最大价值。

Samples

Sample Input 1

3
12 2 3
20
30

Sample Output 1

42

本题输入复杂,需用到字符串。

如果要解释样例,

                   12

             20           30

其中12连着20与30.

#include<bits/stdc++.h>
using namespace std;
int n,a[105][105],s[105],dp[105],ans;
string p;
int main()  
{ 	     
	cin>>n; 	
	getline(cin,p); 	
	for(int i=1;i<=n;i++) 	
	{ 		
		getline(cin,p); 		
		int sum=0; 		
		for(int j=0;j<p.size();j++) 		
		{ 			
			if(p[j]==' ')
			{
				a[i][++s[i]]=sum;
				sum=0;
			}
			if(p[j]>='0'&&p[j]<='9') sum=sum*10+p[j]-'0'; 
		} 	
		a[i][++s[i]]=sum;
	}	 	
	for(int i=n;i>=1;i--)
	{ 		
		dp[i]+=a[i][1]; 		
		int max1=0; 
		for(int j=2;j<=s[i];j++)
		{
			max1=max(max1,dp[a[i][j]]);
		} 				
		dp[i]+=max1; 		
		ans=max(ans,dp[i]); 	
	} 	
	cout<<ans; 	
	return 0;  
}
//aij为第i个层的,连接着j层,i为第几层,j为连接的层数

问题C传球游戏

Description

上体育课的时候,小蛮的老师经常带着同学们一起做游戏。这次,老师带着同学们一起

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
动态规划线性规划和非线性规划是三种不同的优化方法,它们的思想和应用场景不同,具体区别如下: 1. 动态规划动态规划是一种在有重叠子问题和最优子结构的情况下可以采用的算法思想。动态规划通常用于解决多阶段决策问题,每个阶段的决策依赖于前面各个阶段的决策。常见的动态规划问题有最长公共子序列、背包问题等。 2. 线性规划:线性规划是一种优化问题,它的目标是在一组线性约束条件下最大化或最小化线性目标函数的值。线性规划问题通常可以用线性规划算法求解,这种算法的核心是单纯形法。常见的线性规划问题有生产计划、运输问题等。 3. 非线性规划:非线性规划是一类目标函数或约束条件中包含非线性项的优化问题。非线性规划问题通常比线性规划问题更难求解,因为它们的解空间通常是非凸的。常见的非线性规划问题有最小二乘法、无约束优化问题等。 举例来说: 1. 动态规划:最长公共子序列问题是一个经典的动态规划问题。给定两个字符串,求它们的最长公共子序列的长度。这个问题可以用动态规划算法求解,其中状态转移方程为:dp[i][j] = dp[i-1][j-1] + 1,当 s1[i] == s2[j] 时;否则,dp[i][j] = max(dp[i-1][j], dp[i][j-1])。 2. 线性规划:假设一个工厂有 2 种机器可以用于生产产品 A 和 B,每种机器的使用时间和成本如下表所示。现在需要制定一个生产计划,使得生产的产品 A 和 B 的总成本最小,同时满足以下约束条件:每种机器的使用时间不得超过 40 小时,产品 A 和 B 的总生产量分别不得少于 100 和 200。 | 机器 | 生产 A 的时间 | 生产 B 的时间 | A 的成本 | B 的成本 | |------|-------------|-------------|---------|---------| | 1 | 10 | 20 | 2 | 3 | | 2 | 20 | 10 | 3 | 2 | 这个问题可以用线性规划算法求解,其中目标函数为:2A + 3B + 3A + 2B = 5A + 5B,约束条件为:10A + 20B ≤ 400,20A + 10B ≤ 400,A ≥ 100,B ≥ 200。 3. 非线性规划:假设有一组数据点 {(x1, y1), (x2, y2), ..., (xn, yn)},现在要求在所有二次函数 y = ax^2 + bx + c 中找到一个最优的拟合函数,使得实际数据点与拟合函数之间的误差最小。这个问题可以用非线性规划算法求解,其中目标函数为误差平方和,即 min Σ(yi - axi^2 - bxi - c)^2。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值