二维动态规划(收集苹果)

平面上有N*M个格子,每个格子中放着一定数量的苹果。你从左上角的格子开始,每一步只能向下走或是向右走,每次走到一个格子上就把格子里的苹果收集起来,这样下去,你最多能收集到多少个苹果
解这个问题与解其它的DP问题几乎没有什么两样。第一步找到问题的“状态”,第二步找到“状态转移方程”,然后基本上问题就解决了。首先,要找到这个问题中的“状态”是什么?必须注意到的一点是,到达一个格子的方式最多只有两种:从左边来的(除了第一列)和从上边来的(除了第一行)。因此为了求出到达当前格子后最多能收集到多少个苹果,就要先去考察那些能到达当前这个格子的格子,到达它们最多能收集到多少个苹果。 (是不是有点绕,但这句话的本质其实是DP的关键:欲求问题的解,先要去求子问题的解)
经过上面的分析,可以得出问题的状态和状态转移方程。状态S[i][j]表示走到(i, j)这个格子时,最多能收集到多少个苹果。那么,状态转移方程如下:
S[i][j]=A[i][j] + max(S[i-1][j] if i>0 ; S[i][j-1], if j>0)
其中i代表行,j代表列,下标均从0开始;A[i][j]代表格子(i, j)处的苹果数量。
S[i][j]有两种计算方式:
1.对于每一行,从左向右计算,然后从上到下逐行处理;
2. 对于每一列,从上到下计算,然后从左向右逐列处理。这样做的目的是为了在计算S[i][j]时,S[i-1][j]和S[i][j-1]都已经计算出来了。

#include <iostream>
using namespace std;
#define MAX_N 100
#define MAX_M 100
int arr[ MAX_N ][ MAX_M ] = { 0 };
int dp[ MAX_N + 2 ][ MAX_M + 2 ] = { 0 }; 
int main(){
	int n, m;
	cin>> n >> m;  //输入n*m的方格
	int i, j ;
	for( i = 0; i < n; i++){
		for( j = 0; j < m; j++)
			cin>> arr[ i ][ j ];
	} //输入方格中各个格子中的苹果数量
	for( i = 0; i < n; i++){
		for( j = 0; j < m; j++){
			dp[ i + 1 ][ j + 1 ] = dp[ i ][ j + 1] > dp[ i + 1 ][ j ] ? 
						dp[ i ][ j + 1] + arr[ i ][ j ] : dp[ i + 1][ j ] + arr[ i ][ j ]; //动态规划最重要的状态转移方程
		}
	} 
	cout<<dp[i][j]<<endl;
	return 0;
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
动态规划是一种在数学优化中用于求解最优化问题的方法,常用于解决具有重叠子问题和最优子结构的问题,比如二维空间中的物品装箱问题。在MATLAB中,可以使用这种算法来高效地解决二维空间内如何尽可能多地放置满足大小限制的矩形物体,以达到最小化浪费空间的目的。 具体步骤包括: 1. 定义状态:在这个问题中,状态通常是每个位置(i, j)上能够放下多少个物体,或者能否放下一个特定尺寸的物体。 2. 建立状态转移方程:根据当前位置和物体的尺寸,确定是否能放入,并更新当前位置的状态值,要考虑已经放入的物体对后续放置的影响。 3. 初始化:创建一个二维数组来表示状态,通常开始时所有位置都无法放置物体,状态为0。 4. 动态规划遍历:从左上角开始,使用递推的方式填充这个数组,直到遍历完整个二维空间。 5. 最终状态:在状态数组右下角的元素将给出在给定尺寸约束下能放置的最大物体数量。 6. 反向追踪:找到放置路径,即回溯状态数组,记录每个位置的最优解。 以下是一个简单的MATLAB代码示例,用于解决二维装箱问题: ```matlab function [maxObjects, positions] = twoDimensionalBinPacking(rectangles, maxRectSize) % rectangles: 一个矩形数组,每个元素包含矩形的宽度和高度 % maxRectSize: 可以放入的最大矩形尺寸 % 初始化状态矩阵,所有位置都是未被占用 numRows = size(rectangles, 1); numCols = size(rectangles, 2); dp = zeros(numRows, numCols); % 填充状态矩阵 for i = 1:numRows for j = 1:numCols for rect = rectangles if isInside(rect, [i, j], maxRectSize) && dp(i-rect(1), j-rect(2)) == 0 dp(i, j) = dp(i-rect(1), j-rect(2)) + 1; positions{i, j} = rect; % 保存位置信息 end end end end % 找到最大物品数 maxObjects = max(dp(:)); % 返回最大物品数和位置信息 [~, idx] = max(dp(:)); positions = positions(idx); end % 判断一个矩形是否能完全放入指定位置 function isInside(rect, pos, maxRectSize) return pos(1) >= rect(1) && pos(2) >= rect(2) && pos(1) + rect(1) <= maxRectSize(1) && pos(2) + rect(2) <= maxRectSize(2); end ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值