方格取数(动态规划)题解

题目描述:

设有N×N的方格图(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。
某人从图的左上角的AA点出发,可以向下行走,也可以向右走,直到到达右下角的BB点。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从(0, 0)点到(n,n)点共走两次,试找出2条这样的路径,使得取得的数之和为最大。

输入格式:

输入的第一行为一个整数N(表示N×N的方格图),接下来的每行有三个整数,前两个表示位置,第三个数为该位置上所放的数。一行单独的0表示输入结束。
如:
8
6 1 7
3 2 9
2 3 5
1 4 3
3 4 3
6 6 6
1 7 1
0 0 0

输出格式:

输出文件仅包含一个数,表示所有人都渡过河的最少渡河时间:25

思路:

动态表示:

f[k][i][j]表示走了总共k步,第一次走到了横坐标为i 的位置(纵坐标为k-i),第一次走到了横坐标为j的位置(纵坐标为k-j)。

动态转移:

四种情况(下下、下右、右下、右右)

需要注意的:两次走到过同一位置。

if(i==j){

                    f[k][i][j] = w[i][k-i] + max(f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j],f[k-1][i][j]);

                }

else{

                    f[k][i][j] = w[j][k-j]+ w[i][k-i] + max(f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j],f[k-1][i][j]);

                }

AC代码:

#include<iostream>
using namespace std;
const int N = 50;
int n;
int w[N][N];
int f[2*N][N][N];

int max(int a,int b,int c,int d){
    return(max(a,max(b,max(c,d))));
}

int main(){
    cin>>n;
    int a,b,c;
    while(cin>>a>>b>>c){
        if(!a&&!b&&!c) break;
        w[a][b] = c;
    }
    for(int k=2;k<=2*n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(i==j){
                    f[k][i][j] = w[i][k-i] + max(f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j],f[k-1][i][j]);
                }
                else{
                    f[k][i][j] = w[j][k-j]+ w[i][k-i] + max(f[k-1][i-1][j-1],f[k-1][i][j-1],f[k-1][i-1][j],f[k-1][i][j]);
                }
            }
    cout<<f[2*n][n][n]<<endl;
}

加上边界考虑:

#include<iostream>
using namespace std;
int n;
int map[15][15];
int f[25][15][15];
int main() {
    cin >> n;
    int x, y, z;
    while (cin >> x >> y >> z) {
        if (!x && !y && !z) break;
        map[x][y] = z;
    }
    for (int k = 2; k <= 2 * n; k ++ ) 
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= n; j ++ ) {
                int a = k - i, b = k - j;
                if (a >= 1 && a <= n && b >= 1 && b <= n) {
                    int t = max(max(f[k - 1][i - 1][j], f[k - 1][i][j]), max(f[k - 1][i][j - 1], f[k - 1][i - 1][j - 1]));
                    if (i == j) f[k][i][j] = t + map[i][a];
                    else f[k][i][j] = t + map[i][a] + map[j][b];
                }
            }
    cout << f[2 * n][n][n];
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_48419914/article/details/115369778
今日推荐