题解:洛谷 P1004 [NOIP 2000 提高组] 方格取数

【题目来源】

洛谷:P1004 [NOIP 2000 提高组] 方格取数 - 洛谷

【题目描述】

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

image

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

【输入】

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

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

【输出】

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

【输入样例】

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

【输出样例】

67

【解题思路】

image

【算法标签】

《洛谷 P1004 方格取数》 #动态规划,dp# #递归# #费用流# #NOIP提高组# #2000#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

int a[15][15];          // 存储网格中的数值
int dp[15][15][15][15];  // 四维DP数组,记录两条路径的最大和
int n, x, y, num;        // n: 网格大小,x/y: 坐标,num: 数值

/**
 * 辅助函数:返回四个数中的最大值
 */
int f(int a, int b, int c, int d)
{
    return max(max(a, b), max(c, d));
}

int main()
{
    // 输入网格大小n
    cin >> n;
  
    // 输入网格数据,直到遇到x=0结束
    while (cin >> x >> y >> num && x)
    {
        a[x][y] = num;
    }
  
    // 动态规划计算两条路径的最大和
    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++)
                {
                    // 确保两条路径同步前进(i+j == k+l)
                    if (i + j == k + l)
                    {
                        // 状态转移:取四种可能的最大值加上当前两个点的值
                        dp[i][j][k][l] = f(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])
                                          + a[i][j] + a[k][l];
                      
                        // 如果两条路径重合,减去重复计算的值
                        if (i == k && j == l)
                        {
                            dp[i][j][k][l] -= a[k][l];
                        }
                    }
                }
            }
        }
    }
  
    // 输出最终结果(原代码缺少输出语句,这里保持原样)
    return 0;
}

【运行结果】

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
67
posted @ 2026-02-20 19:23  团爸讲算法  阅读(2)  评论(0)    收藏  举报