洛谷P1004 [NOIP2000 提高组] 方格取数

1.题目

题目描述

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

A
 0  0  0  0  0  0  0  0
 0  0 13  0  0  6  0  0
 0  0  0  0  7  0  0  0
 0  0  0 14  0  0  0  0
 0 21  0  0  0  4  0  0
 0  0 15  0  0  0  0  0
 0  0  0  0  0  0  0  0
                       B

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

输入格式

输入的第一行为一个整数 N N N (表示 N × N N \times N N×N 的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的 0 0 0 表示输入结束。

输出格式

只需输出一个整数,表示 2 2 2 条路径上取得的最大的和。

输入输出样例

输入 #1

8
2 3 13
2 6  6
3 5  7
4 4 14
5 2 21
5 6  4
6 3 15
7 2 14
0 0  0

输出 #1

67

2.思路

主要思路:动态规划。该问题可以转化为两个人分别从 A A A 点走各自的路径到 B B B 点,要求两人一路上取走的数值之和最大。

  • 步骤一:定义动态规划数组dp的含义
    定义状态规划数组dp为一四维数组,即dp[i][j][k][l],表示第一个人走到点 ( i , j ) (i, j) (i,j) 及第二个人走到点 ( k , l ) (k, l) (k,l) 一路上取走的数值之和的最大值。
  • 步骤二:定义状态转移方程
    由于只能向下走和向右走,则dp[i][j][k][l]的值与dp[i - 1][j][k - 1][l]、dp[i - 1][j][k][l - 1]、dp[i][j - 1][k - 1][l]dp[i][j - 1][k][l - 1]的状态相关,即dp[i][j][k][l]应取这四个状态中的最大值,再加上点 ( i , j ) (i, j) (i,j) 的值points[i][j]和点 ( k , l ) (k, l) (k,l) 的值points[k][l],所以状态转移方程为 d p [ i ] [ j ] [ k ] [ l ] = max ⁡ ( d p [ i − 1 ] [ j ] [ k − 1 ] [ l ] , d p [ i − 1 ] [ j ] [ k ] [ l − 1 ] , d p [ i ] [ j − 1 ] [ k − 1 ] [ l ] , d p [ i ] [ j − 1 ] [ k ] [ l − 1 ] ) + p o i n t s [ i ] [ j ] + p o i n t s [ k ] [ l ] dp[i][j][k][l] = \max(dp[i - 1][j][k - 1][l], dp[i - 1][j][k][l - 1], dp[i][j - 1][k - 1][l], dp[i][j - 1][k][l - 1]) + points[i][j] + points[k][l] dp[i][j][k][l]=max(dp[i1][j][k1][l],dp[i1][j][k][l1],dp[i][j1][k1][l],dp[i][j1][k][l1])+points[i][j]+points[k][l]但是,根据题目在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字 0 0 0,所以当 i = k i=k i=k j = l j=l j=l 时,由于有一个人取走了该方格中的数,因此只加一次 p o i n t s [ i ] [ j ] points[i][j] points[i][j] p o i n t s [ k ] [ l ] points[k][l] points[k][l]
  • 步骤三:初始化过程转移的初始值
    两人所走路径点的范围为 ( 1 , 1 ) (1,1) (1,1) ( N , N ) (N,N) (N,N) ,则dp[i][0][k][0] = dp[i][0][0][l] = dp[0][j][k][0] = dp[0][j][0][l] = 0

3.代码

import java.util.Scanner;

/**
 * @author xiaoyaosheny
 * @discription 洛谷P1004 [NOIP2000 提高组] 方格取数
 * @date 2021/7/9
 */
public class Main {

    /**
     * 程序入口
     *
     * @param args 输入参数
     */
    public static void main(String[] args) {
        // 获取输入参数
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();      // N x N 方格图
        int[][] points = new int[N + 1][N + 1];
        int x = scanner.nextInt();
        int y = scanner.nextInt();
        int number = scanner.nextInt();
        while (x != 0 && y != 0 && number != 0) {
            points[x][y] = number;
            x = scanner.nextInt();
            y = scanner.nextInt();
            number = scanner.nextInt();
        }
        // 动态规划
        int[][][][] dp = new int[N + 1][N + 1][N + 1][N + 1];
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                for (int k = 1; k <= N; k++) {
                    for (int l = 1; l <= N; l++) {
                        dp[i][j][k][l] = Math.max(Math.max(dp[i - 1][j][k - 1][l], dp[i - 1][j][k][l - 1]), Math.max(dp[i][j - 1][k - 1][l], dp[i][j - 1][k][l - 1])) + points[i][j] + points[k][l];
                        if (i == k && j == l)
                            dp[i][j][k][l] -= points[i][j];
                    }
                }
            }
        }
        // 输出结果
        System.out.println(dp[N][N][N][N]);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值