方格取数的另一个题解 AcWing 1027

题目
在这里插入图片描述
思路:先求出最大值,查找出最大路径上的路径,由下图可知,最大值加上的最后一个数,其位置就是左上角为最大值的位置。查找到,将此数置为0;
在这里插入图片描述
代码实现:

#include<iostream>
#include<cstring>

using namespace std;

const int N = 12;
int f[N][N];
int w[N][N];
int n;
typedef pair<int, int> pii;
pii p1, p2;

int getnum(){
    
    
    memset(f, 0, sizeof f);
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j++){
    
    
            f[i][j] = max(f[i - 1][j], f[i][j - 1]) + w[i][j];
        }
    
    return f[n][n];
}

pii find(int a) //找到所有值和a相等的,在矩阵中最靠左上角的位置,返回左上角的坐标
{
    
    
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n; j++){
    
    
            if(f[i][j] == a) {
    
    
                p1.first = i, p1.second = j;
                return p1;
            }
        }
}

int main(){
    
    
    cin >> n;
    int a, b, c;
    while(cin >> a >> b >> c, a | b | c) w[a][b] = c;
    
    for(int i = 1; i <= n; i++){
    
    
        for(int j = 1; j <= n; j++) cout << w[i][j] << "   " ;
        cout << endl;
    }
    
    /*
    int res = 0;
    res += getnum();
    
    cout << endl;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++) cout << f[i][j] << "   " ;
        cout << endl;
    }
    */
    
    int temp = res;
    //清除使用过的数,因为数组中的数只有指定位置不为0,那么值相等的左上角的位置就是最后加的那个数的位置,具体参考数图
    while(temp){
    
    
        p2 = find(temp);
        temp -= w[p2.first][p2.second];
        w[p2.first][p2.second] = 0;
        
    }
    res += getnum();
    cout << res << endl;
    //这样求出来的数是最大路径上的数之前的最大值和清除之后的最大值的和。
    return 0;
}

这种方法有局限性,如果两次的和的最大值并不包括初始的最大路径,比如,第一次加的值我不取最大值,因为有可能初始最大路径上的值被清除之后,使得之后我的最大路径值变得特别小,如果我不去初始最大路径,然后将该路径上的数清零了之后,求出清零后的当时的最大路径的值,这两条路径的最大值有可能大于之前的两条路径的值。

具体情况如下图所示
在这里插入图片描述
我们取红色路径,56是初始矩形的最大路径值,如果将改路径上的值全部清零,两次路径上的最大值是91;
但是如果取蓝色路径,可以看到两次路径的值为109,大于91;

猜你喜欢

转载自blog.csdn.net/qq_44879626/article/details/108610565