使用二阶动态规划解决方格取数
创始人
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]))

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...