使用二阶动态规划解决方格取数
创始人
2024-04-05 14:38:46
0

题目描述

设有 N×N 的方格图 (N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字 0。如下图所示(见样例):

A0  0  0  0  0  0  0  00  0 13  0  0  6  0  00  0  0  0  7  0  0  00  0  0 14  0  0  0  00 21  0  0  0  4  0  00  0 15  0  0  0  0  00 14  0  0  0  0  0  00  0  0  0  0  0  0  0B

某人从图的左上角的 A 点出发,可以向下行走,也可以向右走,直到到达右下角的 B 点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0)。
此人从 A 点到 B 点共走两次,试找出 2 条这样的路径,使得取得的数之和为最大。

解法

这是典型的动态规划方法,因为每一步的选择影响了下一步的结果。

又因为要找出两条路径之和为最大,所以是一个2维的动态规划问题。

动态规划的典型套路可以总结成:

1. 定义一个变量代表要求的值。本题中就是从A到B两条路径之和。

2. 动态判断该变量的取值。动态的核心就是每次要判断当前变量的取值,一般会出现v = max(v, w),其中w是另外一种计算出v的方法,例如本题中到B点可以有不同的路径,所以要比较不同的路径。

套路有了,下面就是具体的求解了。

1. 由于是2维动态规划,所以变量是一个四维的数组:D[p1, p2]代表了A到点p1与A到p2的两条路径的最大值。

2. 动态更新:从A点开始,发出两条路径,每个点向右或者向下。如下图所示,当前层是p1、p2,下一层是四个可能的点q1、q2、q3、q4,那么就可以更新D[q1, q2]、D[q1, q3]、D[q2, q3]、D[q2, q4]这四个值了。比如

D[q1, q3] = max(D[q1, q3]D[p1, p2] + M[q1] + M[q3])

关键的就是要判断从其他路径到达q1、q3两个点的D[q1, q3](当前的取值)和通过p1, p2两个点到达q1、q3的值(D[p1, p2] + M[q1] + M[q3])哪个是最大的。

注意到题目中的另外一个约束条件:方格中的数会被取走,所以还需要考虑q1, q2, q3, q4之间有重合的情况:

 这种下需要更新的是D[q1, q2],D[q1, q3]、D[q2, q2]、D[q2, q3]这四个值,

对于D[q2, q2] 的更新方法为:

D[q2, q2] = max(D[q2, q2],   D[p1,p2] + M[q2])

代码

import numpy as np
N = int(input())
M = np.zeros((N, N))while 1:t = list(map(int, input().split()))if np.sum(t) > 0:M[t[0] - 1, t[1] - 1] = t[2]else:break# max_v中的每个点的值代表的是从A点到两个点的两条路径的最大值
max_v = np.zeros((N,N,N,N))# 初始化, v1_list是到p1_list中的每个点的最大值
p1_list = [[0, 1]]
v1_list = [M[0, 0] + M[0, 1]]
p2_list = [[1, 0]]
v2_list = [M[0, 0] + M[1, 0]]
max_v[0,0,0,0] = M[0, 0]
max_v[0,0,0,1] = M[0,0] + M[0, 1]
max_v[0,0,1,0] = M[0,0] + M[1, 0]
max_v[0,1,0,0] = M[0,0] + M[0, 1]
max_v[1,0,0,0] = M[0,0] + M[1, 0]
max_v[1,0,0,1] = M[0,0] + M[1, 0] + M[0, 1]
max_v[0,1,1,0] = max_v[1,0,0,1]while len(p1_list) > 0 or len(p2_list) > 0:new_p1_list = []new_v1_list = []new_p2_list = []new_v2_list = []for i in range(len(p1_list)):p1 = p1_list[i]tmp_p1_list = []if p1[0] < N - 1:            p1_right = [p1[0] + 1, p1[1]]tmp_p1_list.append(p1_right)  new_p1_list.append(p1_right)if p1[1] < N - 1:p1_down = [p1[0], p1[1] + 1]tmp_p1_list.append(p1_down)new_p1_list.append(p1_down)  for j in range(len(p2_list)):p2 = p2_list[j]tmp_p2_list = []  if p2[0] < N - 1:            p2_right = [p2[0] + 1, p2[1]]tmp_p2_list.append(p2_right)if p2_right not in new_p2_list:new_p2_list.append(p2_right)    if p2[1] < N - 1:p2_down = [p2[0], p2[1] + 1]tmp_p2_list.append(p2_down)if p2_down not in new_p2_list:new_p2_list.append(p2_down)for l in range(len(tmp_p1_list)):for k in range(len(tmp_p2_list)):new_p1 = tmp_p1_list[l]                    new_p2 = tmp_p2_list[k]t = max_v[new_p1[0], new_p1[1], new_p2[0], new_p2[1]]if new_p1[0] == new_p2[0] and new_p1[1] == new_p2[1]:max_v[new_p1[0], new_p1[1], new_p2[0], new_p2[1]] = max(t, max_v[p1[0], p1[1], p2[0], p2[1]] + M[new_p1[0], new_p1[1]])else:max_v[new_p1[0], new_p1[1], new_p2[0], new_p2[1]] = max(t, max_v[p1[0], p1[1], p2[0], p2[1]] + M[new_p1[0], new_p1[1]] + M[new_p2[0], new_p2[1]])#print(new_p1[0], new_p1[1], new_p2[0], new_p2[1], max_v[new_p1[0], new_p1[1], new_p2[0], new_p2[1]])p1_list = new_p1_listp2_list = new_p2_listv1_list = new_v1_listv2_list = new_v2_listprint(int(max_v[N-1,N-1,N-1,N-1]))

相关内容

热门资讯

保存时出现了1个错误,导致这篇... 当保存文章时出现错误时,可以通过以下步骤解决问题:查看错误信息:查看错误提示信息可以帮助我们了解具体...
汇川伺服电机位置控制模式参数配... 1. 基本控制参数设置 1)设置位置控制模式   2)绝对值位置线性模...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
表格中数据未显示 当表格中的数据未显示时,可能是由于以下几个原因导致的:HTML代码问题:检查表格的HTML代码是否正...
本地主机上的图像未显示 问题描述:在本地主机上显示图像时,图像未能正常显示。解决方法:以下是一些可能的解决方法,具体取决于问...
表格列调整大小出现问题 问题描述:表格列调整大小出现问题,无法正常调整列宽。解决方法:检查表格的布局方式是否正确。确保表格使...
不一致的条件格式 要解决不一致的条件格式问题,可以按照以下步骤进行:确定条件格式的规则:首先,需要明确条件格式的规则是...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...