蓝桥杯算法训练——逗志凡的危机——动态规划+递归

算法训练 逗志芃的危机

题目描述

逗志芃又一次面临了危机。逗志芃的妹子是个聪明绝顶的人,相比之下逗志芃就很菜了。现在她妹子要和他玩一个游戏,这个游戏是这样的:一共有n个数(n是偶数)写成一行,然后两个人轮流取数,每次只能从最前面或者最后面取走一个数,全部取完则游戏结束,之后每个人取走的数的和就是每个人的得分。由于逗志芃妹子很厉害,但他又不想输,所以只能找到你了,你要告诉他最多可以得到多少分。(注意,妹子智商是maxlongint所以是不会犯错的,每次的策略必然最优,而且逗志芃是先手)

输入格式

第一行一个数n,表示有n个数。第二行就是进行游戏的n个数。

输出格式

一个数,逗志凡最高得分

样例输入

2
10 20

样例输出

20

数据规模和约定

例:0<n,m<=1000,每个数不超过10000 。

题目思考

偶数个数字的数列a[N],N%2==0
逗志凡是先手,那直观的想,逗志凡每次都需要找到头尾两端的两个数中的最大的那个,即max(a[0],a[N-1])。
第二轮开始,轮到妹子选取,妹子肯定会选择最大的那个。
为了防止逗志凡短浅,只看到目前最大的,忽视了未来更大的数字,因此我们需要回溯,但是这个是我之前的想法,现在我学习他人的思想,受益良多。

第一种 动态规划

虽然题目是采用动态规划的方式求解的,但是其中还惨和有一点博弈论的思考方式

#include <iostream>
using namespace std;




int main()
{
	//n代表有n个数字 
	int n;
	cin >> n;
	int nums[n];
	
	//ans[n][n]这个二维数组,超越了我对二维数组的认知
	//ans[n][n]代表从第i个数字到第j个数字,逗某人可以获得的最大数值
	//最终的结果就是ans[0][n-1]
	int ans[n][n];
	//输入n个数字
	for(int i=0; i<n ; i++)
	{
		cin >> nums[i];
	}
	
 	//开始进行动态规划算法
 	//中间的ans[L][R]表示L(th)-R(th)的数字的最大值
 	//因为R是从右到左的方向移动的,L是从0->n-1移动的,最终是ans[0][n-1]
 	//所以在这里我的初始状态定义没搞明白,状态转移方程也没明白
	for(int R=0;R<n;R++)
	{
		for(int L=R;L>=0;L--)
		{
			if(L==R)
			{
				//表示只有一个数字,只能被那个女孩子拿走
				//这里不太明白 
				ans[L][R] = 0;
			}
			else if((R-L)&1) //表示还剩下偶数个数字,那就是逗某下手
			{
				ans[L][R] = max(nums[L]+ans[L+1][R],nums[R]+ans[L][R-1]);	
			}
			else
			{
				//女孩子不会手下留情,所以留给逗志凡的会很少
				ans[L][R] = min(ans[L+1][R], ans[L][R-1]); 
			 } 
		}
	}
		
	cout << ans[0][n-1] << endl;
	return 0;
 } 

状态转移方程是这道题目的关键
对于逗先生来说,每次轮到他的时候,剩下偶数个数字。然后我们的目标是让总和最大,于是肯定需要确定

ans[L][R] = max(nums[L]+ans[L+1][R],nums[R]+ans[L][R-1]);	

表示要选取最前面的还是最后面的最好,反正选最大的。
然后就是女友出手

················································
说实话,对动态规划一类的题目还缺乏认识,先写到这,之后继续
················································

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 蓝桥杯算法训练中的采油区域问题是一个典型的动态规划问题。题目给出一个二维矩阵,每个格子代表一个油田,有不同的价值。要求找出一个采油区域,使得采油区域中所有的油田的总价值最大。 解决这个问题可以使用动态规划的思想。我们定义一个二维数组dp,dp[i][j]表示当采油区域的右下角位置为(i, j)时的最大总价值。那么对于dp[i][j],它可以由左边的位置dp[i][j-1]、上边的位置dp[i-1][j]和左上角位置dp[i-1][j-1]推导出来。 具体的状态转移方程为:dp[i][j] = max(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) + matrix[i][j],其中matrix[i][j]代表第i行第j列油田的价值。 在计算dp数组时,循环遍历矩阵的每个位置,并根据状态转移方程更新相应的dp值。最后,dp[m-1][n-1]就是所求的最大总价值,其中m和n分别为矩阵的行数和列数。 具体的Python代码如下: ```python def maxOilValue(matrix): m, n = len(matrix), len(matrix[0]) dp = [[0] * n for _ in range(m)] dp[0][0] = matrix[0][0] for i in range(1, m): dp[i][0] = dp[i-1][0] + matrix[i][0] for j in range(1, n): dp[0][j] = dp[0][j-1] + matrix[0][j] for i in range(1, m): for j in range(1, n): dp[i][j] = max(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) + matrix[i][j] return dp[m-1][n-1] # 测试 matrix = [[3, 7, 9, 2], [2, 1, 3, 6], [8, 5, 6, 4]] print(maxOilValue(matrix)) ``` 以上是用Python解决蓝桥杯算法训练中采油区域问题的方法。在具体实现中,我们使用了一个二维数组来保存每个位置的最大总价值,并应用了动态规划的思想。最后,输出了矩阵中采油区域的最大总价值。 ### 回答2: 采油区域问题是一道经典的算法训练问题,通常使用深度优先搜索算法来解决。在Python中,可以使用递归函数实现深度优先搜索。 蓝桥杯采油区域问题描述了一个由n*n的网格组成的二维地图,每个格子上标有一个非负整数,表示该格子上的石油储量。要求选取一个区域,该区域由相邻的格子组成(上下左右),使得区域中所有格子的石油储量和最大。 解决这个问题的关键是要遍历所有可能的区域,并计算每个区域的石油储量和。可以从地图上的每个位置开始进行深度搜索,将每个位置的格子都作为第一个格子,递归地搜索周围的相邻格子。搜索过程中记录当前区域的石油储量和,并更新最大储量和的值。 以下是一个用Python实现的采油区域问题的代码示例: ```python # 深度优先搜索 def dfs(grid, i, j, visited): m, n = len(grid), len(grid[0]) if i < 0 or i >= m or j < 0 or j >= n or visited[i][j]: return 0 visited[i][j] = True res = grid[i][j] + dfs(grid, i+1, j, visited) + dfs(grid, i-1, j, visited) + dfs(grid, i, j+1, visited) + dfs(grid, i, j-1, visited) return res # 采油区域 def oilArea(grid): m, n = len(grid), len(grid[0]) visited = [[False] * n for _ in range(m)] maxOil = float('-inf') for i in range(m): for j in range(n): maxOil = max(maxOil, dfs(grid, i, j, visited)) return maxOil # 示例 grid = [ [1, 3, 2, 5], [2, 2, 1, 7], [3, 1, 5, 9], [4, 1, 2, 4] ] print(oilArea(grid)) ``` 对于给定的地图,该代码将计算出最大石油储量和,并将结果打印出来。在这个示例中,最大石油储量和为22。 ### 回答3: 采油区域问题是蓝桥杯算法训练中常见的一道题目。题目描述如下:给定一个矩阵,表示一个采油区域,每个单元格的数值代表这个区域的油田价值。现在需要找到一个不相交的矩形区域,使得这个区域内的油田价值之和最大。 解题思路可以采用动态规划的方法。首先定义一个二维数组dp,dp[i][j]表示以坐标(i, j)为右下角的不相交矩形区域的最大油田价值之和。那么,我们可以根据dp[i-1][j-1]、dp[i-1][j]和dp[i][j-1]来更新dp[i][j]的值,即: dp[i][j] = max(dp[i-1][j-1] + oil[i][j], dp[i-1][j], dp[i][j-1]) 其中,oil[i][j]表示坐标(i, j)处的油田价值。 接下来,我们可以通过遍历整个矩阵,不断更新dp数组得到最终的结果。遍历时,我们可以从第一行和第一列开始,因为考虑到边界情况,我们可以初始化一个额外的行和列,将其值设置为0。 最后,我们只需取dp数组中的最大值,即为所求的最大油田价值之和。 在Python中,我们可以用一个二维列表来表示矩阵,并使用嵌套循环来进行遍历和更新dp数组的操作。最后返回dp数组中的最大值即可。 以下是一个实现示例: def maxOil(matrix): rows = len(matrix) cols = len(matrix[0]) dp = [[0] * (cols + 1) for _ in range(rows + 1)] for i in range(1, rows + 1): for j in range(1, cols + 1): dp[i][j] = max(dp[i-1][j-1] + matrix[i-1][j-1], dp[i-1][j], dp[i][j-1]) return dp[rows][cols]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值