1. 礼物问题
就是从左上角到右下角,中间经过的权重选择要是最大的,最后路径权重的累加和是所有可能情况里面最大的,有图论的意思在里面了。
2. 求出最大值
2.1 Matlab
% 题目来源:剑指 Offer 47: 礼物的最大价值
M = [5 1 5 1;
3 5 3 5;
4 2 1 1;
1 5 1 3;
1 5 3 4];
function f = max_gift_value1(M)
% 输入的M就是棋盘中每个礼物的价值
[m,n] = size(M); % 棋盘m行n列
FF = M; % 初始化DP数组和M完全相同,用来保存f(i,j)
% 计算FF的第一列
FF(:,1) = cumsum(M(:,1)); % cumsum函数用来计算累加和
% 计算FF的第一行
FF(1,:) = cumsum(M(1,:));
% 循环计算右下部分的元素
for i = 2:m
for j = 2:n
tem1 = FF(i,j-1) + M(i,j); % 从左边来
tem2 = FF(i-1,j) + M(i,j); % 从上面来
FF(i,j) = max(tem1,tem2);
end
end
f = FF(m,n);%累加的最后一个总和
end
>>>>>>>>>>>>>>>>输出>>>>>>>>>>>>>>>>>>>>
f =
32
2.2 Python
import numpy as np
matrix= np.array([[5,1,5,1],
[3,5,3,5],
[4,2,1,1],
[1,5,1,3],
[1,5,3,4]],
dtype=int)
a,b=matrix.shape
Matrix=matrix
Matrix[:,0]=np.cumsum(Matrix[:,0],axis=0,dtype=int)
Matrix[0,:]=np.cumsum(Matrix[0,:],axis=0,dtype=int)
i=0
j=0
for i in range(1,a):
for j in range(1,b):
num1 = Matrix[i][j]+Matrix[i-1][j]#left
num2 = Matrix[i][j]+Matrix[i][j-1]#up
Matrix[i][j]=max(num1,num2)
print("最大值是", Matrix[a-1][b-1])
print("整个矩阵是",Matrix)
##############输出###############
最大值是 32
整个矩阵是
[[ 5 6 11 12]
[ 8 13 16 21]
[12 15 17 22]
[13 20 21 25]
[14 25 28 32]]
#############################
3. 求出路径
3.1 Matlab
function [f,path] = max_gift_value2(M)
% 输入的M就是棋盘中每个礼物的价值
[m,n] = size(M); % 棋盘m行n列
FF = M; % 初始化DP数组和M完全相同,用来保存f(i,j)
% 计算FF的第一列
FF(:,1) = cumsum(M(:,1)); % cumsum函数用来计算累加和
% 计算FF的第一行
FF(1,:) = cumsum(M(1,:));
% 循环计算右下部分的元素
for i = 2:m
for j = 2:n
tem1 = FF(i,j-1) + M(i,j); % 从左边来
tem2 = FF(i-1,j) + M(i,j); % 从上面来
FF(i,j) = max(tem1,tem2);
end
end
f = FF(m,n);
% 根据程序中得到的DP数组(FF)来推出对应的路径path
path = zeros(m,n); % path全为0和1组成,1表示经过该格子
i = m; j = n;
while i ~= 1 || j ~= 1 % 只要没有回到原点
path(i,j) = 1; % 把path矩阵的第i行第j列变成1(表示访问了这个格子)
if i == 1 % 如果到了第一行
path(1,1:j) = 1; % 剩余的路径沿着左边一直走就可以了
break % 退出循环
end
if j == 1 % 如果到了第一列
path(1:i,1) = 1; % 剩余的路径沿着上方一直走就可以了
break % 退出循环
end
tmp1 = FF(i-1,j); % 上方单元格FF的值
tmp2 = FF(i,j-1); % 左边单元格FF的值
ind = find([tmp1,tmp2] == (FF(i,j)-M(i,j)),1); % 看哪个值等于FF(i,j)-M(i,j)
if ind == 1 % 如果上方单元格FF的值等于FF(i,j)-M(i,j)
i = i-1; % 说明上一步沿着上方来的
else % 如果左边单元格FF的值等于FF(i,j)-M(i,j)
j = j-1; % 说明上一步沿着左边来的
end
end
end
3.2 Python
import numpy as np
matrix= np.array([[5,1,5,1],
[3,5,3,5],
[4,2,1,1],
[1,5,1,3],
[1,5,3,4]],
dtype=int)
a,b=matrix.shape
Matrix=matrix.copy()
Matrix[:,0]=np.cumsum(Matrix[:,0],axis=0,dtype=int)
Matrix[0,:]=np.cumsum(Matrix[0,:],axis=0,dtype=int)
i=0
j=0
for i in range(1,a):
for j in range(1,b):
num1 = Matrix[i][j]+Matrix[i-1][j]#left
num2 = Matrix[i][j]+Matrix[i][j-1]#up
Matrix[i][j]=max(num1,num2)
print("最大值是", Matrix[a-1][b-1])
print("整个矩阵是", Matrix)
i=a
j=b
path= np.zeros((a,b))
while i!=0 and j!=0:
path[i-1][j-1]=1
if i==0:
path[0][0:j]=1
break
if j==0:
path[0:i][0]=1
break
tmp1 = Matrix[i-2][j-1] #up
tmp2 = Matrix[i-1][j-2] #left
if Matrix[i-1][j-1] - matrix[i-1][j-1] == tmp1:
i=i-1
else:
j=j-1
print(path)
>>>>>>>>>>输出>>>>>>>>>>>>>>>>>>>>>>>
>#总和最大权重的路径为
>array([[1., 0., 0., 0.],
[1., 1., 0., 0.],
[0., 1., 0., 0.],
[0., 1., 0., 0.],
[0., 1., 1., 1.]])
4.总结
求最大值的时候是顺序的,求路径得先求出累加和再反向推出路径,用累加后的矩阵的相邻两个值相减,看是否值跟原矩阵相等