AcWing1027.方格取数

发布于:2022-12-03 ⋅ 阅读:(310) ⋅ 点赞:(0)

题目描述

设有 N × N N×N N×N 的方格图,我们在其中的某些方格中填入正整数,而其它的方格中则放入数字 0 0 0。如下图所示:

2.gif

某人从图中的左上角 A 出发,可以向下行走,也可以向右行走,直到到达右下角的 B 点。

在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。

此人从 A 点到 B 点共走了两次,试找出两条这样的路径,使得取得的数字和为最大。

输入格式

第一行为一个整数 N N N,表示 N × N N×N N×N 的方格图。

接下来的每行有三个整数,第一个为行号数,第二个为列号数,第三个为在该行、该列上所放的数。

行和列编号从 1 1 1 开始。

一行“ 0   0   0 0\ 0\ 0 0 0 0”表示结束。

输出格式

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

数据范围

N ≤ 10 ​ N≤10​ N10​

输入样例:

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

算法

数字三角形模型

f [ i 1 , j 1 , i 2 , j 2 ] ​ f[i1,j1,i2,j2]​ f[i1,j1,i2,j2]定义为 : 从 ( 1 , 1 ) (1,1) (1,1), ( 1 , 1 ) (1,1) (1,1)​​走到 ( i 1 , j 1 ) , ( i 2 , j 2 ) (i1,j1),(i2,j2) (i1,j1),(i2,j2)​​能获得的最大花生数目.
这里我们可以设两个人同时走,然后得出 k = i 1 + j 1 = i 2 + j 2 k = i1 + j1 = i2 + j2 k=i1+j1=i2+j2
所以我们用 k k k这一维来表示步数和,通过 k , i 1 , i 2 k,i1,i2 k,i1,i2计算出 j 1 , j 2 j1,j2 j1,j2
由上面的两条性质可以推出三维的状态转移方程在这里插入图片描述

(图片来自yxc大佬)

得出代码

#include <bits/stdc++.h>

using namespace std;

const int N = 11;
int f[2 * N][N][N];//第一维为后两维之和,所以开两倍
int w[N][N];

int main()
{
    int n;
    scanf("%d", &n);
    int a, b, c;
    while (cin >> a >> b >> c && a || b) w[a][b] = c;
    
    for(int k = 2; k <= 2 * n; k ++ )
        for(int i1 = 1; i1 <= n; i1 ++ )
            for(int i2 = 1; i2 <= n; i2 ++ )
            {
                int j1 = k - i1, j2 = k - i2;
                int t = w[i1][j1] + w[i2][j2] * (i1 != i2);
                if(j1 >= 1 && j1 <= n && j2 > 0 && j2 <= n)
                {
                    int &x = f[k][i1][i2];
                    x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);
                    x = max(x, f[k - 1][i1 - 1][i2] + t);
                    x = max(x, f[k - 1][i1][i2] + t);
                    x = max(x, f[k - 1][i1][i2 - 1] + t);
                }
            }
    printf("%d\n", f[n + n][n][n]);
    return 0;
}

网站公告

今日签到

点亮在社区的每一天
去签到